Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73e7d6f986 | ||
|
|
145001d26e | ||
|
|
5d2d7ce979 | ||
|
|
4dc21ab2b0 | ||
|
|
df6ee73e05 | ||
|
|
587af33179 | ||
|
|
3b381b037c | ||
|
|
0968fc56eb | ||
|
|
13044cb5b0 | ||
|
|
580b03f2b9 | ||
|
|
543d4bb6b3 | ||
|
|
21d87d5a80 | ||
|
|
194719e7ba | ||
|
|
dc666fc770 | ||
|
|
50a76e6b27 | ||
|
|
be4d3170db | ||
|
|
7b97002230 | ||
|
|
6319d63e1f | ||
|
|
2e18478b5c | ||
|
|
0ef93edd56 | ||
|
|
d6a3661e58 | ||
|
|
be404436d7 | ||
|
|
b1ebefb854 | ||
|
|
f8aa2701b6 | ||
|
|
034dfc8e6b | ||
|
|
a6b6898697 | ||
|
|
0e5a0bfa7b | ||
|
|
6c01f5eace | ||
|
|
ef2c34c55f | ||
|
|
7c1582c06f | ||
|
|
367e2666c6 | ||
|
|
209a401113 | ||
|
|
837349e3d3 | ||
|
|
e66602aa5c | ||
|
|
082f8e1b04 | ||
|
|
07716474d3 | ||
|
|
f335cc4269 | ||
|
|
f19750cfaf | ||
|
|
46810f69ca | ||
|
|
a7247c594b | ||
|
|
8de7876f72 | ||
|
|
49f75f5070 | ||
|
|
4ff543efc7 | ||
|
|
8af5145b56 | ||
|
|
a31242cdc5 | ||
|
|
e20df1e7aa | ||
|
|
960a368175 | ||
|
|
49cb86dfe9 | ||
|
|
b644ec58af |
+10
-1
@@ -17,6 +17,7 @@
|
||||
#
|
||||
|
||||
# To enable enterprise-only features please add your environment variable to the .env file then make your way to /auth/setup to select your license and follow instructions.
|
||||
|
||||
CALCOM_LICENSE_KEY=
|
||||
# Signature token for the Cal.com License API (used for self-hosted integrations)
|
||||
# We will give you a token when we provide you with a license key this ensure you and only you can communicate with the Cal.com License API for your license key
|
||||
@@ -192,7 +193,10 @@ NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0
|
||||
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=
|
||||
STRIPE_TEAM_MONTHLY_PRICE_ID=
|
||||
STRIPE_TEAM_PRODUCT_ID=
|
||||
# It is a price ID in the product with id STRIPE_ORG_PRODUCT_ID
|
||||
STRIPE_ORG_MONTHLY_PRICE_ID=
|
||||
STRIPE_ORG_PRODUCT_ID=
|
||||
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
STRIPE_WEBHOOK_SECRET_APPS=
|
||||
STRIPE_PRIVATE_KEY=
|
||||
@@ -285,7 +289,7 @@ NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL=
|
||||
# use organizations
|
||||
ORGANIZATIONS_ENABLED=
|
||||
NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS=30
|
||||
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE=3700 # $37.00 per seat
|
||||
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37 # $37.00 per seat
|
||||
|
||||
# This variable should only be set to 1 or true if you want to autolink external provider sign-ups with
|
||||
# existing organizations based on email domain address
|
||||
@@ -402,6 +406,11 @@ NEXT_PUBLIC_WEBSITE_TERMS_URL=
|
||||
# [0: silly & upwards, 1: trace & upwards, 2: debug & upwards, 3: info & upwards, 4: warn & upwards, 5: error & fatal, 6: fatal]
|
||||
NEXT_PUBLIC_LOGGER_LEVEL=
|
||||
|
||||
# For storing Daily Video recordings on S3 Bucket
|
||||
CAL_VIDEO_BUCKET_NAME=
|
||||
CAL_VIDEO_BUCKET_REGION=
|
||||
CAL_VIDEO_ASSUME_ROLE_ARN=
|
||||
|
||||
# Used to use Replexica SDK, a tool for real-time AI-powered localization
|
||||
REPLEXICA_API_KEY=
|
||||
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
@@ -1,9 +0,0 @@
|
||||
- [x] Refactor individual calendar links functions to create the variables and just use the variables in the string literal instead of functions being called in the string literal
|
||||
- [x] Must ensure during review that logically there is no change in the functionality of booking-single-view.tsx
|
||||
|
||||
|
||||
- Testing
|
||||
- [x] Verify Google Calendar, Ics, Office 365 - Compare with Production
|
||||
- [x] Event Description, Booking title, Booking location, Start time, End time - All correct
|
||||
- [x] Recurring event?
|
||||
- [x] Dynamic Group booking?
|
||||
@@ -38,7 +38,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.147",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.151",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
X_CAL_PLATFORM_EMBED,
|
||||
} from "@calcom/platform-constants";
|
||||
|
||||
import { CalendarServiceExceptionFilter } from "./filters/calendar-service-exception.filter";
|
||||
import { TRPCExceptionFilter } from "./filters/trpc-exception.filter";
|
||||
|
||||
export const bootstrap = (app: NestExpressApplication): NestExpressApplication => {
|
||||
@@ -76,6 +77,7 @@ export const bootstrap = (app: NestExpressApplication): NestExpressApplication =
|
||||
app.useGlobalFilters(new ZodExceptionFilter());
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
app.useGlobalFilters(new TRPCExceptionFilter());
|
||||
app.useGlobalFilters(new CalendarServiceExceptionFilter());
|
||||
|
||||
app.use(cookieParser());
|
||||
|
||||
|
||||
@@ -39,11 +39,15 @@ import { Request } from "express";
|
||||
import { BOOKING_READ, BOOKING_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import {
|
||||
CancelBookingInput,
|
||||
CancelBookingInput_2024_08_13,
|
||||
CancelBookingInputPipe,
|
||||
CancelSeatedBookingInput_2024_08_13,
|
||||
GetBookingOutput_2024_08_13,
|
||||
GetBookingsOutput_2024_08_13,
|
||||
RescheduleBookingInput,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
RescheduleBookingInputPipe,
|
||||
RescheduleSeatedBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import {
|
||||
CreateBookingInputPipe,
|
||||
@@ -65,9 +69,12 @@ import {
|
||||
@DocsTags("Bookings")
|
||||
@ApiHeader({
|
||||
name: "cal-api-version",
|
||||
description: `Must be set to \`2024-08-13\``,
|
||||
description: `Must be set to ${VERSION_2024_08_13}`,
|
||||
example: VERSION_2024_08_13,
|
||||
required: true,
|
||||
schema: {
|
||||
default: VERSION_2024_08_13,
|
||||
},
|
||||
})
|
||||
export class BookingsController_2024_08_13 {
|
||||
private readonly logger = new Logger("BookingsController_2024_08_13");
|
||||
@@ -99,7 +106,7 @@ export class BookingsController_2024_08_13 {
|
||||
],
|
||||
},
|
||||
description:
|
||||
"Accepts different types of booking input: CreateBookingInput_2024_08_13, CreateInstantBookingInput_2024_08_13, or CreateRecurringBookingInput_2024_08_13",
|
||||
"Accepts different types of booking input: Create Booking (Option 1), Create Instant Booking (Option 2), or Create Recurring Booking (Option 3)",
|
||||
})
|
||||
@ApiExtraModels(
|
||||
CreateBookingInput_2024_08_13,
|
||||
@@ -172,9 +179,19 @@ export class BookingsController_2024_08_13 {
|
||||
@UseGuards(BookingUidGuard)
|
||||
@ApiOperation({
|
||||
summary: "Reschedule a booking",
|
||||
description:
|
||||
"Reschedule a booking by passing `:bookingUid` of the booking that should be rescheduled and pass request body with a new start time to create a new booking.",
|
||||
description: "Reschedule a booking or seated booking",
|
||||
})
|
||||
@ApiBody({
|
||||
schema: {
|
||||
oneOf: [
|
||||
{ $ref: getSchemaPath(RescheduleBookingInput_2024_08_13) },
|
||||
{ $ref: getSchemaPath(RescheduleSeatedBookingInput_2024_08_13) },
|
||||
],
|
||||
},
|
||||
description:
|
||||
"Accepts different types of reschedule booking input: Reschedule Booking (Option 1) or Reschedule Seated Booking (Option 2)",
|
||||
})
|
||||
@ApiExtraModels(RescheduleBookingInput_2024_08_13, RescheduleSeatedBookingInput_2024_08_13)
|
||||
async rescheduleBooking(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@Body(new RescheduleBookingInputPipe())
|
||||
@@ -199,6 +216,17 @@ export class BookingsController_2024_08_13 {
|
||||
For seated bookings to cancel one individual booking provide :bookingUid and :seatUid in the request body. For recurring seated bookings it is not possible to cancel all of them with 1 call
|
||||
like with non-seated recurring bookings by providing recurring bookind uid - you have to cancel each recurrence booking by its bookingUid + seatUid.`,
|
||||
})
|
||||
@ApiBody({
|
||||
schema: {
|
||||
oneOf: [
|
||||
{ $ref: getSchemaPath(CancelBookingInput_2024_08_13) },
|
||||
{ $ref: getSchemaPath(CancelSeatedBookingInput_2024_08_13) },
|
||||
],
|
||||
},
|
||||
description:
|
||||
"Accepts different types of cancel booking input: Cancel Booking (Option 1) or Cancel Seated Booking (Option 2)",
|
||||
})
|
||||
@ApiExtraModels(CancelBookingInput_2024_08_13, CancelSeatedBookingInput_2024_08_13)
|
||||
async cancelBooking(
|
||||
@Req() request: Request,
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
|
||||
@@ -40,6 +40,8 @@ import {
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
const googleMeetUrl = "https://meet.google.com/abc-def-ghi";
|
||||
|
||||
describe("Seated bookings", () => {
|
||||
let app: INestApplication;
|
||||
let organization: Team;
|
||||
@@ -330,7 +332,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
location: googleMeetUrl,
|
||||
bookingFieldsResponses: {
|
||||
codingLanguage: "TypeScript",
|
||||
},
|
||||
@@ -383,6 +385,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: body.attendee.name,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
@@ -418,6 +424,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: body.attendee.name,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
@@ -797,7 +807,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
location: googleMeetUrl,
|
||||
bookingFieldsResponses: {
|
||||
codingLanguage: "TypeScript",
|
||||
},
|
||||
@@ -850,6 +860,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: body.attendee.name,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
@@ -885,6 +899,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: body.attendee.name,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
@@ -910,7 +928,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
location: googleMeetUrl,
|
||||
bookingFieldsResponses: {
|
||||
codingLanguage: "TypeScript",
|
||||
},
|
||||
@@ -966,6 +984,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: nameAttendeeOne,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: createdRecurringSeatedBooking[0].attendees[0].metadata,
|
||||
});
|
||||
@@ -982,6 +1004,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: nameAttendeeTwo,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
@@ -1017,6 +1043,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: nameAttendeeOne,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: createdRecurringSeatedBooking[0].attendees[0].metadata,
|
||||
});
|
||||
@@ -1030,6 +1060,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
bookingFieldsResponses: {
|
||||
name: nameAttendeeTwo,
|
||||
...body.bookingFieldsResponses,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
},
|
||||
metadata: body.metadata,
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { CancelBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs
|
||||
import { CreateBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/create-booking.output";
|
||||
import { MarkAbsentBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/mark-absent.output";
|
||||
import { RescheduleBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/reschedule-booking.output";
|
||||
import { CreateEventTypeOutput_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/outputs/create-event-type.output";
|
||||
import { CreateScheduleInput_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/inputs/create-schedule.input";
|
||||
import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.module";
|
||||
import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service";
|
||||
@@ -27,10 +28,12 @@ import { withApiAuth } from "test/utils/withApiAuth";
|
||||
import {
|
||||
CAL_API_VERSION_HEADER,
|
||||
SUCCESS_STATUS,
|
||||
VERSION_2024_06_14,
|
||||
VERSION_2024_08_13,
|
||||
X_CAL_CLIENT_ID,
|
||||
} from "@calcom/platform-constants";
|
||||
import {
|
||||
CreateEventTypeInput_2024_06_14,
|
||||
GetBookingOutput_2024_08_13,
|
||||
GetBookingsOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
@@ -95,6 +98,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
|
||||
organization = await teamRepositoryFixture.create({
|
||||
name: `user-bookings-organization-${randomString()}`,
|
||||
isOrganization: true,
|
||||
});
|
||||
oAuthClient = await createOAuthClient(organization.id);
|
||||
|
||||
@@ -146,7 +150,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
startTime: new Date(Date.UTC(2020, 0, 8, 13, 0, 0)),
|
||||
endTime: new Date(Date.UTC(2020, 0, 8, 14, 0, 0)),
|
||||
title: "peer coding lets goo",
|
||||
uid: "booking-in-the-past",
|
||||
uid: `booking-in-the-past-${randomString()}`,
|
||||
eventType: {
|
||||
connect: {
|
||||
id: eventTypeId,
|
||||
@@ -326,6 +330,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
});
|
||||
|
||||
it("should create a booking", async () => {
|
||||
const googleMeetUrl = "https://meet.google.com/abc-def-ghi";
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 8, 13, 0, 0)).toISOString(),
|
||||
eventTypeId,
|
||||
@@ -335,7 +340,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
location: googleMeetUrl,
|
||||
bookingFieldsResponses: {
|
||||
customField: "customValue",
|
||||
},
|
||||
@@ -389,6 +394,10 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
email: body.attendee.email,
|
||||
...body.bookingFieldsResponses,
|
||||
guests: body.guests,
|
||||
location: {
|
||||
optionValue: googleMeetUrl,
|
||||
value: "link",
|
||||
},
|
||||
});
|
||||
expect(data.guests).toEqual(body.guests);
|
||||
|
||||
@@ -972,6 +981,64 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("createdAt filter", () => {
|
||||
it("should should get bookings after specified createdAt time", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(`/v2/bookings?afterCreatedAt=${createdRecurringBooking[1].createdAt}`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: GetBookingsOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
const data: (
|
||||
| BookingOutput_2024_08_13
|
||||
| RecurringBookingOutput_2024_08_13
|
||||
| GetSeatedBookingOutput_2024_08_13
|
||||
)[] = responseBody.data;
|
||||
expect(data.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
it("should should get bookings before specified createdAt time", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(`/v2/bookings?beforeCreatedAt=${createdRecurringBooking[0].createdAt}`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: GetBookingsOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
const data: (
|
||||
| BookingOutput_2024_08_13
|
||||
| RecurringBookingOutput_2024_08_13
|
||||
| GetSeatedBookingOutput_2024_08_13
|
||||
)[] = responseBody.data;
|
||||
expect(data.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
it("should should get bookings in createdAt range", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(
|
||||
`/v2/bookings?afterCreatedAt=${createdRecurringBooking[0].createdAt}&beforeCreatedAt=${createdRecurringBooking[1].createdAt}`
|
||||
)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: GetBookingsOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
const data: (
|
||||
| BookingOutput_2024_08_13
|
||||
| RecurringBookingOutput_2024_08_13
|
||||
| GetSeatedBookingOutput_2024_08_13
|
||||
)[] = responseBody.data;
|
||||
expect(data.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should should sort bookings by start in descending order", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(`/v2/bookings?eventTypeId=${eventTypeId}&sortStart=desc`)
|
||||
@@ -1537,6 +1604,351 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("booking location", () => {
|
||||
const address = "123 Main St";
|
||||
const link = "https://cal.com/join/123456";
|
||||
const phone = "+37121999999";
|
||||
|
||||
let eventTypeWithAllLocationsId: number;
|
||||
it("can create event type with all locations except google meet", async () => {
|
||||
const eventTypeBody: CreateEventTypeInput_2024_06_14 = {
|
||||
title: "book using any location",
|
||||
slug: "book-using-any-location",
|
||||
lengthInMinutes: 15,
|
||||
locations: [
|
||||
{
|
||||
type: "integration",
|
||||
integration: "cal-video",
|
||||
},
|
||||
{
|
||||
type: "address",
|
||||
address,
|
||||
public: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
link,
|
||||
public: true,
|
||||
},
|
||||
{
|
||||
type: "phone",
|
||||
phone,
|
||||
public: true,
|
||||
},
|
||||
{
|
||||
type: "attendeeAddress",
|
||||
},
|
||||
{
|
||||
type: "attendeePhone",
|
||||
},
|
||||
{
|
||||
type: "attendeeDefined",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const eventTypeResponse = await request(app.getHttpServer())
|
||||
.post("/api/v2/event-types")
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
|
||||
.send(eventTypeBody)
|
||||
.expect(201);
|
||||
const eventTypeResponseBody: CreateEventTypeOutput_2024_06_14 = eventTypeResponse.body;
|
||||
const createdEventType = eventTypeResponseBody.data;
|
||||
expect(createdEventType).toHaveProperty("id");
|
||||
expect(createdEventType.locations).toHaveLength(7);
|
||||
expect(createdEventType.locations).toEqual(createdEventType.locations);
|
||||
eventTypeWithAllLocationsId = createdEventType.id;
|
||||
});
|
||||
|
||||
it("can book with cal video location", async () => {
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "integration",
|
||||
integration: "cal-video",
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(
|
||||
createdBooking.location?.startsWith("http") || createdBooking.location === "integrations:daily"
|
||||
).toEqual(true);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can book with address location", async () => {
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "address",
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(address);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can book with link location", async () => {
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "link",
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(link);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can book with link location", async () => {
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "phone",
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(phone);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can book with attendeeAddress location", async () => {
|
||||
const attendeeAddress = "123 Example St, City, Valhalla";
|
||||
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "attendeeAddress",
|
||||
address: attendeeAddress,
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(attendeeAddress);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
xit("can book with attendeeAddress location", async () => {
|
||||
const attendeePhone = "+37120993151";
|
||||
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "attendeePhone",
|
||||
phone: attendeePhone,
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(attendeePhone);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can book with attendeeDefined location", async () => {
|
||||
const attendeeDefinedLocation = "namek 100";
|
||||
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "attendeeDefined",
|
||||
location: attendeeDefinedLocation,
|
||||
},
|
||||
};
|
||||
|
||||
const bookingResponse = await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201);
|
||||
|
||||
const bookingResponseBody: CreateBookingOutput_2024_08_13 = bookingResponse.body;
|
||||
const createdBooking = bookingResponseBody.data;
|
||||
expect(createdBooking).toHaveProperty("id");
|
||||
|
||||
if (responseDataIsBooking(createdBooking)) {
|
||||
expect(createdBooking.location).toEqual(attendeeDefinedLocation);
|
||||
await bookingsRepositoryFixture.deleteById(createdBooking.id);
|
||||
} else {
|
||||
throw new Error("Unexpected response data type");
|
||||
}
|
||||
});
|
||||
|
||||
it("can't book with not location that is not in event type", async () => {
|
||||
const bookingBody: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "integration",
|
||||
integration: "google-meet",
|
||||
},
|
||||
};
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it("can't book with invalid location type", async () => {
|
||||
const bookingBody = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeWithAllLocationsId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: {
|
||||
type: "blablabala",
|
||||
},
|
||||
};
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(bookingBody)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(400);
|
||||
});
|
||||
});
|
||||
|
||||
function responseDataIsRecurranceBooking(data: any): data is RecurringBookingOutput_2024_08_13 {
|
||||
return (
|
||||
!Array.isArray(data) &&
|
||||
|
||||
@@ -229,8 +229,7 @@ export class BookingsService_2024_08_13 {
|
||||
const fetchedBookings: { bookings: { id: number }[] } = await getAllUserBookings({
|
||||
bookingListingByStatus: queryParams.status || [],
|
||||
skip: queryParams.skip ?? 0,
|
||||
// note(Lauris): we substract -1 because getAllUSerBookings child function adds +1 for some reason
|
||||
take: queryParams.take ? queryParams.take - 1 : 100,
|
||||
take: queryParams.take ?? 100,
|
||||
filters: this.inputService.transformGetBookingsFilters(queryParams),
|
||||
ctx: {
|
||||
user,
|
||||
@@ -564,7 +563,9 @@ export class BookingsService_2024_08_13 {
|
||||
throw new BadRequestException(`Booking with uid ${bookingUid} has no event type`);
|
||||
}
|
||||
|
||||
const eventType = await this.eventTypesRepository.getEventTypeByIdIncludeUsersAndTeam(booking.eventTypeId);
|
||||
const eventType = await this.eventTypesRepository.getEventTypeByIdIncludeUsersAndTeam(
|
||||
booking.eventTypeId
|
||||
);
|
||||
if (!eventType) {
|
||||
throw new BadRequestException(`Booking with uid ${bookingUid} has no event type`);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "@/ee/bookings/2024-08-13/services/output.service";
|
||||
import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service";
|
||||
import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository";
|
||||
import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service";
|
||||
import { hashAPIKey, isApiKey, stripApiKey } from "@/lib/api-key";
|
||||
import { ApiKeysRepository } from "@/modules/api-keys/api-keys-repository";
|
||||
import { BookingSeatRepository } from "@/modules/booking-seat/booking-seat.repository";
|
||||
@@ -15,13 +16,17 @@ import { BadRequestException, Injectable, NotFoundException } from "@nestjs/comm
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { CreationSource } from "@prisma/client";
|
||||
import { isURL, isPhoneNumber } from "class-validator";
|
||||
import { Request } from "express";
|
||||
import { DateTime } from "luxon";
|
||||
import { NextApiRequest } from "next/types";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventTypeMetaDataSchema } from "@calcom/platform-libraries/event-types";
|
||||
import {
|
||||
EventTypeMetaDataSchema,
|
||||
apiToInternalintegrationsMapping,
|
||||
} from "@calcom/platform-libraries/event-types";
|
||||
import {
|
||||
CancelBookingInput,
|
||||
CancelBookingInput_2024_08_13,
|
||||
@@ -35,7 +40,8 @@ import {
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
RescheduleSeatedBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { EventType } from "@calcom/prisma/client";
|
||||
import { BookingInputLocation_2024_08_13 } from "@calcom/platform-types/bookings/2024-08-13/inputs/location.input";
|
||||
import { EventType, PlatformOAuthClient } from "@calcom/prisma/client";
|
||||
|
||||
type BookingRequest = NextApiRequest & { userId: number | undefined } & OAuthRequestParams;
|
||||
|
||||
@@ -77,6 +83,7 @@ export class InputBookingsService_2024_08_13 {
|
||||
private readonly config: ConfigService,
|
||||
private readonly apiKeyRepository: ApiKeysRepository,
|
||||
private readonly bookingSeatRepository: BookingSeatRepository,
|
||||
private readonly outputEventTypesService: OutputEventTypesService_2024_06_14,
|
||||
private readonly platformBookingsService: PlatformBookingsService,
|
||||
private readonly usersRepository: UsersRepository
|
||||
) {}
|
||||
@@ -91,23 +98,21 @@ export class InputBookingsService_2024_08_13 {
|
||||
const newRequest = { ...request };
|
||||
const userId = (await this.createBookingRequestOwnerId(request)) ?? undefined;
|
||||
|
||||
const location = request.body.location || request.body.meetingUrl;
|
||||
this.logger.log(`createBookingRequest_2024_04_15`, {
|
||||
this.logger.log(`createBookingRequest_2024_08_13`, {
|
||||
requestId: request.get("X-Request-Id"),
|
||||
ownerId: userId,
|
||||
location,
|
||||
oAuthClientParams,
|
||||
});
|
||||
|
||||
if (oAuthClientParams) {
|
||||
Object.assign(newRequest, { userId, ...oAuthClientParams, platformBookingLocation: location });
|
||||
Object.assign(newRequest, { userId, ...oAuthClientParams });
|
||||
newRequest.body = {
|
||||
...bodyTransformed,
|
||||
noEmail: !oAuthClientParams.arePlatformEmailsEnabled,
|
||||
creationSource: CreationSource.API_V2,
|
||||
};
|
||||
} else {
|
||||
Object.assign(newRequest, { userId, platformBookingLocation: location });
|
||||
Object.assign(newRequest, { userId });
|
||||
newRequest.body = { ...bodyTransformed, noEmail: false, creationSource: CreationSource.API_V2 };
|
||||
}
|
||||
|
||||
@@ -143,6 +148,10 @@ export class InputBookingsService_2024_08_13 {
|
||||
)
|
||||
: inputBooking.attendee.email;
|
||||
|
||||
const inputLocation = inputBooking.location || inputBooking.meetingUrl;
|
||||
this.isBookingLocationWithEventTypeLocations(inputLocation, eventType);
|
||||
const location = inputLocation ? this.transformLocation(inputLocation) : undefined;
|
||||
|
||||
return {
|
||||
start: startTime.toISO(),
|
||||
end: endTime.toISO(),
|
||||
@@ -159,6 +168,7 @@ export class InputBookingsService_2024_08_13 {
|
||||
email: attendeeEmail ?? "",
|
||||
attendeePhoneNumber: inputBooking.attendee.phoneNumber,
|
||||
guests,
|
||||
location,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -196,17 +206,14 @@ export class InputBookingsService_2024_08_13 {
|
||||
const newRequest = { ...request };
|
||||
const userId = (await this.createBookingRequestOwnerId(request)) ?? undefined;
|
||||
|
||||
const location = request.body.location || request.body.meetingUrl;
|
||||
|
||||
if (oAuthClientParams) {
|
||||
Object.assign(newRequest, {
|
||||
userId,
|
||||
...oAuthClientParams,
|
||||
platformBookingLocation: location,
|
||||
noEmail: !oAuthClientParams.arePlatformEmailsEnabled,
|
||||
});
|
||||
} else {
|
||||
Object.assign(newRequest, { userId, platformBookingLocation: location });
|
||||
Object.assign(newRequest, { userId });
|
||||
}
|
||||
|
||||
newRequest.body = bodyTransformed.map((event) => ({
|
||||
@@ -217,6 +224,144 @@ export class InputBookingsService_2024_08_13 {
|
||||
return newRequest as unknown as BookingRequest;
|
||||
}
|
||||
|
||||
transformLocation(location: string | BookingInputLocation_2024_08_13): {
|
||||
value: string;
|
||||
optionValue: string;
|
||||
} {
|
||||
if (typeof location === "string") {
|
||||
// note(Lauris): this is for backwards compatibility because before switching to booking location objects
|
||||
// we only received a string. If someone is complaining that their location is not displaying as a URL
|
||||
// or whatever check that they are not providing a string for bookign location but one of the input objects.
|
||||
if (isURL(location, { require_protocol: false }) || location.startsWith("www.")) {
|
||||
return {
|
||||
value: "link",
|
||||
optionValue: location,
|
||||
};
|
||||
}
|
||||
|
||||
if (isPhoneNumber(location)) {
|
||||
return {
|
||||
value: "phone",
|
||||
optionValue: location,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
value: "somewhereElse",
|
||||
optionValue: location,
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "integration") {
|
||||
const integration = apiToInternalintegrationsMapping[location.integration];
|
||||
if (!integration) {
|
||||
throw new BadRequestException(`Invalid integration: ${location.integration}`);
|
||||
}
|
||||
return {
|
||||
value: integration,
|
||||
optionValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "address") {
|
||||
return {
|
||||
value: "inPerson",
|
||||
optionValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "attendeeAddress") {
|
||||
return {
|
||||
value: "attendeeInPerson",
|
||||
optionValue: location.address,
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "link") {
|
||||
return {
|
||||
value: "link",
|
||||
optionValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "phone") {
|
||||
return {
|
||||
value: "userPhone",
|
||||
optionValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "organizersDefaultApp") {
|
||||
return {
|
||||
value: "conferencing",
|
||||
optionValue: "",
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "attendeePhone") {
|
||||
return {
|
||||
value: "phone",
|
||||
optionValue: location.phone,
|
||||
};
|
||||
}
|
||||
|
||||
if (location.type === "attendeeDefined") {
|
||||
return {
|
||||
value: "somewhereElse",
|
||||
optionValue: location.location,
|
||||
};
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
`Booking location with type ${(location as BookingInputLocation_2024_08_13).type} not valid.`
|
||||
);
|
||||
}
|
||||
|
||||
private isBookingLocationWithEventTypeLocations(
|
||||
inputBookingLocation: undefined | string | BookingInputLocation_2024_08_13,
|
||||
dbEventType: EventType
|
||||
) {
|
||||
if (!inputBookingLocation || typeof inputBookingLocation === "string") {
|
||||
// note(Lauris): for backwards compatibility because we had string locations before so let them pass.
|
||||
return true;
|
||||
}
|
||||
|
||||
const eventTypeLocations = this.outputEventTypesService.transformLocations(dbEventType.locations);
|
||||
const allowedLocationTypes = eventTypeLocations.map((location) => location.type);
|
||||
|
||||
const isAllowed = allowedLocationTypes.includes(inputBookingLocation.type);
|
||||
if (!isAllowed) {
|
||||
throw new BadRequestException(
|
||||
`Booking location with type ${inputBookingLocation.type} not valid for event type with id=${
|
||||
dbEventType.id
|
||||
}. The event type has following location types: ${allowedLocationTypes.join(
|
||||
", "
|
||||
)}, and only these types are allowed for booking location.`
|
||||
);
|
||||
}
|
||||
|
||||
if (inputBookingLocation.type === "integration" && "integration" in inputBookingLocation) {
|
||||
const allowedIntegrations = eventTypeLocations
|
||||
.filter((location) => location.type === "integration")
|
||||
.map((location) => location.integration);
|
||||
|
||||
const isAllowedIntegration = allowedIntegrations.includes(inputBookingLocation.integration);
|
||||
if (!isAllowedIntegration) {
|
||||
throw new BadRequestException(
|
||||
`Booking location with integration ${
|
||||
inputBookingLocation.integration
|
||||
} not valid for event type with id=${
|
||||
dbEventType.id
|
||||
}. The event type has following integrations: ${allowedIntegrations.join(
|
||||
", "
|
||||
)}, and only these integrations are allowed for booking location.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async transformInputCreateRecurringBooking(
|
||||
inputBooking: CreateRecurringBookingInput_2024_08_13,
|
||||
platformClientId?: string
|
||||
@@ -262,6 +407,10 @@ export class InputBookingsService_2024_08_13 {
|
||||
)
|
||||
: inputBooking.attendee.email;
|
||||
|
||||
const inputLocation = inputBooking.location || inputBooking.meetingUrl;
|
||||
this.isBookingLocationWithEventTypeLocations(inputLocation, eventType);
|
||||
const location = inputLocation ? this.transformLocation(inputLocation) : undefined;
|
||||
|
||||
for (let i = 0; i < repeatsTimes; i++) {
|
||||
const endTime = startTime.plus({ minutes: eventType.length });
|
||||
|
||||
@@ -281,6 +430,7 @@ export class InputBookingsService_2024_08_13 {
|
||||
name: inputBooking.attendee.name,
|
||||
email: attendeeEmail,
|
||||
guests,
|
||||
location,
|
||||
},
|
||||
schedulingType: eventType.schedulingType,
|
||||
});
|
||||
@@ -482,6 +632,8 @@ export class InputBookingsService_2024_08_13 {
|
||||
queryParams.eventTypeIds || (queryParams.eventTypeId ? [queryParams.eventTypeId] : undefined),
|
||||
afterUpdatedDate: queryParams.afterUpdatedAt,
|
||||
beforeUpdatedDate: queryParams.beforeUpdatedAt,
|
||||
afterCreatedDate: queryParams.afterCreatedAt,
|
||||
beforeCreatedDate: queryParams.beforeCreatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -29,7 +29,12 @@ import {
|
||||
} from "@nestjs/common";
|
||||
import { ApiHeader, ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
|
||||
import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import {
|
||||
EVENT_TYPE_READ,
|
||||
EVENT_TYPE_WRITE,
|
||||
SUCCESS_STATUS,
|
||||
VERSION_2024_06_14,
|
||||
} from "@calcom/platform-constants";
|
||||
import {
|
||||
UpdateEventTypeInput_2024_06_14,
|
||||
GetEventTypesQuery_2024_06_14,
|
||||
@@ -45,8 +50,12 @@ import {
|
||||
@DocsTags("Event Types")
|
||||
@ApiHeader({
|
||||
name: "cal-api-version",
|
||||
description: `Must be set to \`2024-06-14\``,
|
||||
description: `Must be set to ${VERSION_2024_06_14}`,
|
||||
example: VERSION_2024_06_14,
|
||||
required: true,
|
||||
schema: {
|
||||
default: VERSION_2024_06_14,
|
||||
},
|
||||
})
|
||||
export class EventTypesController_2024_06_14 {
|
||||
constructor(
|
||||
|
||||
+5
-1
@@ -39,8 +39,12 @@ import {
|
||||
@DocsTags("Schedules")
|
||||
@ApiHeader({
|
||||
name: "cal-api-version",
|
||||
description: `Must be set to \`2024-06-11\``,
|
||||
description: `Must be set to ${VERSION_2024_06_11}`,
|
||||
example: VERSION_2024_06_11,
|
||||
required: true,
|
||||
schema: {
|
||||
default: VERSION_2024_06_11,
|
||||
},
|
||||
})
|
||||
@ApiHeader({
|
||||
name: "Authorization",
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { filterReqHeaders } from "@/lib/filterReqHeaders";
|
||||
import { ArgumentsHost, Catch, ExceptionFilter, Logger } from "@nestjs/common";
|
||||
import { Request } from "express";
|
||||
|
||||
import { ERROR_STATUS } from "@calcom/platform-constants";
|
||||
import {
|
||||
CalendarAppError,
|
||||
CalendarAppDelegationCredentialInvalidGrantError,
|
||||
CalendarAppDelegationCredentialError,
|
||||
CalendarAppDelegationCredentialConfigurationError,
|
||||
CalendarAppDelegationCredentialClientIdNotAuthorizedError,
|
||||
CalendarAppDelegationCredentialNotSetupError,
|
||||
} from "@calcom/platform-libraries/app-store";
|
||||
import { Response } from "@calcom/platform-types";
|
||||
|
||||
type CalendarError =
|
||||
| CalendarAppError
|
||||
| CalendarAppDelegationCredentialInvalidGrantError
|
||||
| CalendarAppDelegationCredentialError
|
||||
| CalendarAppDelegationCredentialConfigurationError
|
||||
| CalendarAppDelegationCredentialNotSetupError
|
||||
| CalendarAppDelegationCredentialClientIdNotAuthorizedError;
|
||||
@Catch(
|
||||
CalendarAppError,
|
||||
CalendarAppDelegationCredentialInvalidGrantError,
|
||||
CalendarAppDelegationCredentialError,
|
||||
CalendarAppDelegationCredentialConfigurationError,
|
||||
CalendarAppDelegationCredentialClientIdNotAuthorizedError,
|
||||
CalendarAppDelegationCredentialNotSetupError
|
||||
)
|
||||
export class CalendarServiceExceptionFilter implements ExceptionFilter {
|
||||
private readonly logger = new Logger("CalendarServiceExceptionFilter");
|
||||
|
||||
catch(exception: CalendarError, host: ArgumentsHost) {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
const request = ctx.getRequest<Request>();
|
||||
|
||||
const requestId = request.headers["X-Request-Id"];
|
||||
|
||||
this.logger.error(`Calendar Service Exception Filter: ${exception?.message}`, {
|
||||
exception,
|
||||
body: request.body,
|
||||
headers: filterReqHeaders(request.headers),
|
||||
url: request.url,
|
||||
method: request.method,
|
||||
requestId,
|
||||
});
|
||||
|
||||
response.status(400).json({
|
||||
status: ERROR_STATUS,
|
||||
timestamp: new Date().toISOString(),
|
||||
path: request.url,
|
||||
error: { code: exception.name, message: exception.message },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,20 @@ import { IncomingHttpHeaders } from "http";
|
||||
|
||||
export function filterReqHeaders(headers: IncomingHttpHeaders): Partial<IncomingHttpHeaders> {
|
||||
return {
|
||||
"Content-Type": headers["content-type"],
|
||||
"User-Agent": headers["user-agent"],
|
||||
"Content-Type": headers["Content-Type"] ?? headers["content-type"],
|
||||
Authorization: headers["Authorization"] ?? headers["authorization"],
|
||||
"X-Cal-Client-Id": headers["X-Cal-Client-Id"] ?? headers["x-cal-client-id"],
|
||||
"Cal-Api-Version": headers["Cal-Api-Version"] ?? headers["cal-api-version"],
|
||||
"X-Request-Id": headers["X-Request-Id"] ?? headers["x-request-id"],
|
||||
// IP-related headers
|
||||
"User-Agent": headers["User-agent"] ?? headers["user-agent"],
|
||||
"X-Forwarded-For": headers["x-forwarded-for"],
|
||||
"X-Forwarded-Host": headers["x-forwarded-host"],
|
||||
"CF-Connecting-IP": headers["cf-connecting-ip"],
|
||||
"CloudFront-Viewer-Address": headers["cloudfront-viewer-address"],
|
||||
// Vercel headers
|
||||
"x-vercel-id": headers["x-vercel-id"],
|
||||
"x-vercel-deployment-url": headers["x-vercel-deployment-url"],
|
||||
"x-vercel-country": headers["x-vercel-country"],
|
||||
"x-vercel-region": headers["x-vercel-region"],
|
||||
Host: headers["host"],
|
||||
"X-Vercel-Id": headers["x-vercel-id"],
|
||||
"X-Vercel-Deployment-Url": headers["x-vercel-deployment-url"],
|
||||
"X-Vercel-Country": headers["x-vercel-country"],
|
||||
"X-Vercel-Region": headers["x-vercel-region"],
|
||||
Host: headers["Host"] ?? headers["host"],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
Redirect,
|
||||
UnauthorizedException,
|
||||
Req,
|
||||
HttpException,
|
||||
} from "@nestjs/common";
|
||||
import { ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
import { plainToInstance } from "class-transformer";
|
||||
@@ -56,7 +57,7 @@ export type OAuthCallbackState = {
|
||||
})
|
||||
@DocsTags("Conferencing")
|
||||
export class ConferencingController {
|
||||
private readonly logger = new Logger("Platform Gcal Provider");
|
||||
private readonly logger = new Logger("ConferencingController");
|
||||
|
||||
constructor(
|
||||
private readonly tokensRepository: TokensRepository,
|
||||
@@ -144,6 +145,10 @@ export class ConferencingController {
|
||||
@Query("error") error: string | undefined,
|
||||
@Query("error_description") error_description: string | undefined
|
||||
): Promise<{ url: string }> {
|
||||
if (!state) {
|
||||
throw new BadRequestException("Missing `state` query param");
|
||||
}
|
||||
|
||||
const decodedCallbackState: OAuthCallbackState = JSON.parse(state);
|
||||
try {
|
||||
const userId = await this.tokensRepository.getAccessTokenOwnerId(decodedCallbackState.accessToken);
|
||||
@@ -169,6 +174,9 @@ export class ConferencingController {
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException || error instanceof Error) {
|
||||
this.logger.error(error.message);
|
||||
}
|
||||
return {
|
||||
url: decodedCallbackState.onErrorReturnTo ?? "",
|
||||
};
|
||||
|
||||
+7
@@ -26,6 +26,7 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository
|
||||
import { randomString } from "test/utils/randomString";
|
||||
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { slugify } from "@calcom/platform-libraries";
|
||||
import { ApiSuccessResponse } from "@calcom/platform-types";
|
||||
|
||||
const CLIENT_REDIRECT_URI = "http://localhost:4321";
|
||||
@@ -228,6 +229,9 @@ describe("OAuth Client Users Endpoints", () => {
|
||||
expect(responseBody.data.user.timeFormat).toEqual(requestBody.timeFormat);
|
||||
expect(responseBody.data.user.locale).toEqual(requestBody.locale);
|
||||
expect(responseBody.data.user.avatarUrl).toEqual(requestBody.avatarUrl);
|
||||
const [emailUser, emailDomain] = responseBody.data.user.email.split("@");
|
||||
const [domainName, TLD] = emailDomain.split(".");
|
||||
expect(responseBody.data.user.username).toEqual(slugify(`${emailUser}-${domainName}-${TLD}`));
|
||||
expect(responseBody.data.accessToken).toBeDefined();
|
||||
expect(responseBody.data.refreshToken).toBeDefined();
|
||||
|
||||
@@ -546,6 +550,9 @@ describe("OAuth Client Users Endpoints", () => {
|
||||
expect(responseBody.data.email).toEqual(
|
||||
OAuthClientUsersService.getOAuthUserEmail(oAuthClient.id, userUpdatedEmail)
|
||||
);
|
||||
const [emailUser, emailDomain] = responseBody.data.email.split("@");
|
||||
const [domainName, TLD] = emailDomain.split(".");
|
||||
expect(responseBody.data.username).toEqual(slugify(`${emailUser}-${domainName}-${TLD}`));
|
||||
expect(responseBody.data.locale).toEqual(Locales.PT_BR);
|
||||
});
|
||||
|
||||
|
||||
@@ -123,7 +123,9 @@ export class OAuthClientUsersService {
|
||||
if (body.email) {
|
||||
const emailWithOAuthId = OAuthClientUsersService.getOAuthUserEmail(oAuthClientId, body.email);
|
||||
body.email = emailWithOAuthId;
|
||||
const newUsername = slugify(emailWithOAuthId);
|
||||
const [emailUser, emailDomain] = emailWithOAuthId.split("@");
|
||||
const [domainName, TLD] = emailDomain.split(".");
|
||||
const newUsername = slugify(`${emailUser}-${domainName}-${TLD}`);
|
||||
await this.userRepository.updateUsername(userId, newUsername);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -30,5 +30,7 @@ export class CreateDelegationCredentialInput {
|
||||
})
|
||||
@Expose()
|
||||
@Type(() => Object)
|
||||
serviceAccountKey!: GoogleServiceAccountKeyInput | MicrosoftServiceAccountKeyInput;
|
||||
serviceAccountKey!: (GoogleServiceAccountKeyInput | MicrosoftServiceAccountKeyInput) & {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
+10
-8
@@ -38,6 +38,15 @@ export class OrganizationsDelegationCredentialService {
|
||||
delegatedServiceAccountUser: User,
|
||||
body: UpdateDelegationCredentialInput
|
||||
) {
|
||||
const delegationCredential =
|
||||
await this.organizationsDelegationCredentialRepository.findByIdWithWorkspacePlatform(
|
||||
delegationCredentialId
|
||||
);
|
||||
|
||||
if (!delegationCredential) {
|
||||
throw new NotFoundException(`DelegationCredential with id ${delegationCredentialId} not found`);
|
||||
}
|
||||
|
||||
if (body.enabled !== undefined) {
|
||||
await this.updateDelegationCredentialEnabled(
|
||||
orgId,
|
||||
@@ -49,15 +58,8 @@ export class OrganizationsDelegationCredentialService {
|
||||
if (body.serviceAccountKey !== undefined) {
|
||||
await this.updateDelegationCredentialServiceAccountKey(delegationCredentialId, body.serviceAccountKey);
|
||||
}
|
||||
const delegationCredential =
|
||||
await this.organizationsDelegationCredentialRepository.findByIdWithWorkspacePlatform(
|
||||
delegationCredentialId
|
||||
);
|
||||
if (!delegationCredential) {
|
||||
throw new NotFoundException(`DelegationCredential with id ${delegationCredentialId} not found`);
|
||||
}
|
||||
|
||||
return delegationCredential;
|
||||
return { ...delegationCredential, enabled: body?.enabled ?? delegationCredential?.enabled };
|
||||
}
|
||||
|
||||
async updateDelegationCredentialEnabled(
|
||||
|
||||
@@ -47,8 +47,12 @@ import { ApiResponse } from "@calcom/platform-types";
|
||||
@DocsTags("Slots")
|
||||
@ApiHeader({
|
||||
name: "cal-api-version",
|
||||
description: `Must be set to \`2024-09-04\``,
|
||||
description: `Must be set to ${VERSION_2024_09_04}`,
|
||||
example: VERSION_2024_09_04,
|
||||
required: true,
|
||||
schema: {
|
||||
default: VERSION_2024_09_04,
|
||||
},
|
||||
})
|
||||
export class SlotsController_2024_09_04 {
|
||||
constructor(private readonly slotsService: SlotsService_2024_09_04) {}
|
||||
|
||||
@@ -3597,16 +3597,17 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"description": "Accepts different types of booking input: CreateBookingInput_2024_08_13, CreateInstantBookingInput_2024_08_13, or CreateRecurringBookingInput_2024_08_13",
|
||||
"description": "Accepts different types of booking input: Create Booking (Option 1), Create Instant Booking (Option 2), or Create Recurring Booking (Option 3)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@@ -3648,10 +3649,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3886,10 +3888,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3922,15 +3925,16 @@
|
||||
"post": {
|
||||
"operationId": "BookingsController_2024_08_13_rescheduleBooking",
|
||||
"summary": "Reschedule a booking",
|
||||
"description": "Reschedule a booking by passing `:bookingUid` of the booking that should be rescheduled and pass request body with a new start time to create a new booking.",
|
||||
"description": "Reschedule a booking or seated booking",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3942,6 +3946,24 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"description": "Accepts different types of reschedule booking input: Reschedule Booking (Option 1) or Reschedule Seated Booking (Option 2)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/RescheduleBookingInput_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/RescheduleSeatedBookingInput_2024_08_13"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "",
|
||||
@@ -3968,10 +3990,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3983,6 +4006,24 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"description": "Accepts different types of cancel booking input: Cancel Booking (Option 1) or Cancel Seated Booking (Option 2)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/CancelBookingInput_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/CancelSeatedBookingInput_2024_08_13"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
@@ -4008,10 +4049,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4067,10 +4109,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4116,10 +4159,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4183,10 +4227,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4232,10 +4277,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4292,10 +4338,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"description": "Must be set to 2024-08-13",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-08-13"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4938,10 +4985,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-14`",
|
||||
"description": "Must be set to 2024-06-14",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-14"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -4987,10 +5035,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-14`",
|
||||
"description": "Must be set to 2024-06-14",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-14"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5064,10 +5113,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-14`",
|
||||
"description": "Must be set to 2024-06-14",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-14"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5111,10 +5161,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-14`",
|
||||
"description": "Must be set to 2024-06-14",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-14"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5168,10 +5219,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-14`",
|
||||
"description": "Must be set to 2024-06-14",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-14"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5640,6 +5692,16 @@
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "The number of items to skip",
|
||||
"example": 0,
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -5677,10 +5739,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -5727,10 +5790,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -5769,10 +5833,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -5810,10 +5875,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5857,10 +5923,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -5914,10 +5981,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-06-11`",
|
||||
"description": "Must be set to 2024-06-11",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-06-11"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -6040,10 +6108,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-09-04`",
|
||||
"description": "Must be set to 2024-09-04",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-09-04"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -6220,10 +6289,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-09-04`",
|
||||
"description": "Must be set to 2024-09-04",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-09-04"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -6262,10 +6332,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-09-04`",
|
||||
"description": "Must be set to 2024-09-04",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-09-04"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -6300,10 +6371,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-09-04`",
|
||||
"description": "Must be set to 2024-09-04",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-09-04"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -6347,10 +6419,11 @@
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-09-04`",
|
||||
"description": "Must be set to 2024-09-04",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "2024-09-04"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -9637,7 +9710,6 @@
|
||||
"eightxeight-video",
|
||||
"discord-video",
|
||||
"demodesk-video",
|
||||
"campsite-conferencing",
|
||||
"campfire-video",
|
||||
"around-video"
|
||||
],
|
||||
@@ -11671,7 +11743,10 @@
|
||||
"default": false
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
@@ -11810,7 +11885,11 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"description": "You can store any additional data you want here.\nMetadata must have at most 50 keys, each key up to 40 characters.\nValues can be strings (up to 500 characters), numbers, or booleans.",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
@@ -11888,7 +11967,11 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"description": "You can store any additional data you want here.\nMetadata must have at most 50 keys, each key up to 40 characters.\nValues can be strings (up to 500 characters), numbers, or booleans.",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
@@ -15017,7 +15100,11 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"description": "You can store any additional data you want here.\nMetadata must have at most 50 keys, each key up to 40 characters.\nValues can be strings (up to 500 characters), numbers, or booleans.",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
@@ -15129,7 +15216,10 @@
|
||||
"default": false
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
@@ -15407,7 +15497,11 @@
|
||||
"example": "CalTeam"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"description": "You can store any additional data you want here.\nMetadata must have at most 50 keys, each key up to 40 characters.\nValues can be strings (up to 500 characters), numbers, or booleans.",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -15425,7 +15519,10 @@
|
||||
"minLength": 1
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
},
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
@@ -15468,7 +15565,10 @@
|
||||
"minLength": 1
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -15529,7 +15629,11 @@
|
||||
"example": "CalTeam"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"description": "You can store any additional data you want here.\nMetadata must have at most 50 keys, each key up to 40 characters.\nValues can be strings (up to 500 characters), numbers, or booleans.",
|
||||
"example": {
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -16233,6 +16337,153 @@
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"BookingInputAddressLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "address",
|
||||
"description": "only allowed value for type is `address` - it refers to address defined by the organizer."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"BookingInputAttendeeAddressLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "attendeeAddress",
|
||||
"description": "only allowed value for type is `attendeeAddress`"
|
||||
},
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "123 Example St, City, Country"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"BookingInputAttendeeDefinedLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "attendeeDefined",
|
||||
"description": "only allowed value for type is `attendeeDefined`"
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"example": "321 Example St, City, Country"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"location"
|
||||
]
|
||||
},
|
||||
"BookingInputAttendeePhoneLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "attendeePhone",
|
||||
"description": "only allowed value for type is `attendeePhone`"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"example": "+37120993151"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"phone"
|
||||
]
|
||||
},
|
||||
"BookingInputIntegrationLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integration",
|
||||
"description": "only allowed value for type is `integration`"
|
||||
},
|
||||
"integration": {
|
||||
"type": "string",
|
||||
"example": "cal-video",
|
||||
"enum": [
|
||||
"cal-video",
|
||||
"google-meet",
|
||||
"zoom",
|
||||
"whereby-video",
|
||||
"whatsapp-video",
|
||||
"webex-video",
|
||||
"telegram-video",
|
||||
"tandem",
|
||||
"sylaps-video",
|
||||
"skype-video",
|
||||
"sirius-video",
|
||||
"signal-video",
|
||||
"shimmer-video",
|
||||
"salesroom-video",
|
||||
"roam-video",
|
||||
"riverside-video",
|
||||
"ping-video",
|
||||
"office365-video",
|
||||
"mirotalk-video",
|
||||
"jitsi",
|
||||
"jelly-video",
|
||||
"jelly-conferencing",
|
||||
"huddle",
|
||||
"facetime-video",
|
||||
"element-call-video",
|
||||
"eightxeight-video",
|
||||
"discord-video",
|
||||
"demodesk-video",
|
||||
"campfire-video",
|
||||
"around-video"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"integration"
|
||||
]
|
||||
},
|
||||
"BookingInputLinkLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "link",
|
||||
"description": "only allowed value for type is `link` - it refers to link defined by the organizer."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"BookingInputPhoneLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "phone",
|
||||
"description": "only allowed value for type is `phone` - it refers to phone defined by the organizer."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"ValidateBookingLocation_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"Attendee": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -16356,9 +16607,30 @@
|
||||
"deprecated": true
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "Location for this booking. Displayed in email and calendar event.",
|
||||
"example": "https://example.com/meeting"
|
||||
"description": "One of the event type locations. If instead of passing one of the location objects as required by schema you are still passing a string please use an object.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeDefinedLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeePhoneLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputIntegrationLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputLinkLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputPhoneLocation_2024_08_13"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
@@ -16425,9 +16697,30 @@
|
||||
"deprecated": true
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "Location for this booking. Displayed in email and calendar event.",
|
||||
"example": "https://example.com/meeting"
|
||||
"description": "One of the event type locations. If instead of passing one of the location objects as required by schema you are still passing a string please use an object.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeDefinedLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeePhoneLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputIntegrationLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputLinkLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputPhoneLocation_2024_08_13"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
@@ -16500,9 +16793,30 @@
|
||||
"deprecated": true
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "Location for this booking. Displayed in email and calendar event.",
|
||||
"example": "https://example.com/meeting"
|
||||
"description": "One of the event type locations. If instead of passing one of the location objects as required by schema you are still passing a string please use an object.",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeAddressLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeeDefinedLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputAttendeePhoneLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputIntegrationLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputLinkLocation_2024_08_13"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/BookingInputPhoneLocation_2024_08_13"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
@@ -17671,6 +17985,51 @@
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"RescheduleBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"description": "Start time in ISO 8601 format for the new booking",
|
||||
"example": "2024-08-13T10:00:00Z"
|
||||
},
|
||||
"rescheduledBy": {
|
||||
"type": "string",
|
||||
"description": "Email of the person who is rescheduling the booking - only needed when rescheduling a booking that requires a confirmation.\nIf event type owner email is provided then rescheduled booking will be automatically confirmed. If attendee email or no email is passed then the event type\nowner will have to confirm the rescheduled booking."
|
||||
},
|
||||
"reschedulingReason": {
|
||||
"type": "string",
|
||||
"example": "User requested reschedule",
|
||||
"description": "Reason for rescheduling the booking"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"start"
|
||||
]
|
||||
},
|
||||
"RescheduleSeatedBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"description": "Start time in ISO 8601 format for the new booking",
|
||||
"example": "2024-08-13T10:00:00Z"
|
||||
},
|
||||
"rescheduledBy": {
|
||||
"type": "string",
|
||||
"description": "Email of the person who is rescheduling the booking - only needed when rescheduling a booking that requires a confirmation.\nIf event type owner email is provided then rescheduled booking will be automatically confirmed. If attendee email or no email is passed then the event type\nowner will have to confirm the rescheduled booking."
|
||||
},
|
||||
"seatUid": {
|
||||
"type": "string",
|
||||
"example": "3be561a9-31f1-4b8e-aefc-9d9a085f0dd1",
|
||||
"description": "Uid of the specific seat within booking."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"start",
|
||||
"seatUid"
|
||||
]
|
||||
},
|
||||
"RescheduleBookingOutput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -17705,6 +18064,32 @@
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"CancelBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cancellationReason": {
|
||||
"type": "string",
|
||||
"example": "User requested cancellation"
|
||||
},
|
||||
"cancelSubsequentBookings": {
|
||||
"type": "boolean",
|
||||
"description": "For recurring non-seated booking - if true, cancel booking with the bookingUid of the individual recurrence and all recurrences that come after it."
|
||||
}
|
||||
}
|
||||
},
|
||||
"CancelSeatedBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"seatUid": {
|
||||
"type": "string",
|
||||
"example": "3be561a9-31f1-4b8e-aefc-9d9a085f0dd1",
|
||||
"description": "Uid of the specific seat within booking."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"seatUid"
|
||||
]
|
||||
},
|
||||
"CancelBookingOutput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
"@calcom/platform-libraries/event-types": ["../../../packages/platform/libraries/event-types.ts"],
|
||||
"@calcom/platform-libraries/slots": ["../../../packages/platform/libraries/slots.ts"],
|
||||
"@calcom/platform-libraries/emails": ["../../../packages/platform/libraries/emails.ts"],
|
||||
"@calcom/platform-libraries/schedules": ["../../../packages/platform/libraries/schedules.ts"]
|
||||
"@calcom/platform-libraries/schedules": ["../../../packages/platform/libraries/schedules.ts"],
|
||||
"@calcom/platform-libraries/app-store": ["../../../packages/platform/libraries/app-store.ts"]
|
||||
},
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
@@ -8,4 +8,8 @@ export const generateMetadata = async () =>
|
||||
(t) => t("create_your_org_description")
|
||||
);
|
||||
|
||||
export default EnterprisePage;
|
||||
const ServerPageWrapper = async () => {
|
||||
return <EnterprisePage />;
|
||||
};
|
||||
|
||||
export default ServerPageWrapper;
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { getTranslate } from "app/_utils";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import CreateNewOutOfOfficeEntryButton from "@calcom/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton";
|
||||
import { OutOfOfficeEntriesList } from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
|
||||
import OutOfOfficeEntriesList from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
|
||||
import { OutOfOfficeToggleGroup } from "@calcom/features/settings/outOfOffice/OutOfOfficeToggleGroup";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
|
||||
+2
-3
@@ -3,11 +3,10 @@ import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/about-view";
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/about-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
+2
-3
@@ -3,11 +3,10 @@ import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/add-teams-view";
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/add-teams-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
@@ -0,0 +1,29 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies } from "next/headers";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/onboarding-handover";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("handover_onboarding_page_title"),
|
||||
(t) => t("handover_onboarding_page_description")
|
||||
);
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
</LayoutWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerPage;
|
||||
+2
-3
@@ -3,11 +3,10 @@ import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/onboard-members-view";
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/onboard-members-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
@@ -7,7 +7,6 @@ import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequir
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
import { type inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/create-new-view";
|
||||
|
||||
@@ -17,7 +16,11 @@ export const generateMetadata = async () =>
|
||||
(t) => t("organizations_description")
|
||||
);
|
||||
|
||||
const getData = withAppDirSsr<inferSSRProps<typeof getServerSideProps>>(getServerSideProps);
|
||||
type Props = {
|
||||
isOrg: boolean;
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr<Props>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/payment-status-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("organization_onboarding_status"),
|
||||
(t) => t("organization_onboarding_status_description")
|
||||
);
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
</LayoutWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerPage;
|
||||
@@ -7,17 +7,20 @@ import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequir
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
import { type inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/platform/new/create-new-view";
|
||||
|
||||
type Props = {
|
||||
isOrg: boolean;
|
||||
};
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("set_up_your_platform_organization"),
|
||||
(t) => t("platform_organization_description")
|
||||
);
|
||||
|
||||
const getData = withAppDirSsr<inferSSRProps<typeof getServerSideProps>>(getServerSideProps);
|
||||
const getData = withAppDirSsr<Props>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
|
||||
@@ -8,4 +8,8 @@ export const generateMetadata = async () =>
|
||||
(t) => t("no_meeting_found")
|
||||
);
|
||||
|
||||
export default NoMeetingFound;
|
||||
const ServerPage = async () => {
|
||||
return <NoMeetingFound />;
|
||||
};
|
||||
|
||||
export default ServerPage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
|
||||
import { createTRPCReact } from "@trpc/react-query";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useState } from "react";
|
||||
import superjson from "superjson";
|
||||
|
||||
import { ENDPOINTS } from "@calcom/trpc/react/shared";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
|
||||
import { httpBatchLink, httpLink, loggerLink, splitLink, TRPCClientError } from "@trpc/client";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { NextRequest } from "next/server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
import { AVATAR_FALLBACK } from "@calcom/lib/constants";
|
||||
import { AVATAR_FALLBACK, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
const querySchema = z.object({
|
||||
@@ -47,7 +47,8 @@ async function handler(req: NextRequest, { params }: { params: Params }) {
|
||||
img = data;
|
||||
} catch (e) {
|
||||
// If anything goes wrong or avatar is not found, use default avatar
|
||||
return NextResponse.redirect(AVATAR_FALLBACK, 302);
|
||||
const url = new URL(AVATAR_FALLBACK, WEBAPP_URL).toString();
|
||||
return NextResponse.redirect(url, 302);
|
||||
}
|
||||
|
||||
const decoded = img.toString().replace("data:image/png;base64,", "").replace("data:image/jpeg;base64,", "");
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { IS_PLAIN_CHAT_ENABLED } from "@calcom/lib/constants";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
@@ -20,6 +21,11 @@ const responseSchema = z.object({
|
||||
});
|
||||
|
||||
async function handler() {
|
||||
// Early return if Plain Chat is not enabled
|
||||
if (!IS_PLAIN_CHAT_ENABLED) {
|
||||
return NextResponse.json({ error: "Plain Chat is not enabled" }, { status: 404 });
|
||||
}
|
||||
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
if (!session?.user?.email) {
|
||||
return NextResponse.json({ error: "Unauthorized - No session email found" }, { status: 401 });
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
|
||||
@@ -903,33 +903,23 @@ type NoShowProps = {
|
||||
};
|
||||
|
||||
const Attendee = (attendeeProps: AttendeeProps & NoShowProps) => {
|
||||
const { email, name, bookingUid, isBookingInPast, noShow: noShowAttendee, phoneNumber } = attendeeProps;
|
||||
const { email, name, bookingUid, isBookingInPast, noShow, phoneNumber } = attendeeProps;
|
||||
const { t } = useLocale();
|
||||
|
||||
const [noShow, setNoShow] = useState(noShowAttendee);
|
||||
const utils = trpc.useUtils();
|
||||
const [openDropdown, setOpenDropdown] = useState(false);
|
||||
const { copyToClipboard, isCopied } = useCopy();
|
||||
|
||||
const noShowMutation = trpc.viewer.markNoShow.useMutation({
|
||||
onSuccess: async (data) => {
|
||||
showToast(data.message, "success");
|
||||
utils.viewer.bookings.invalidate();
|
||||
},
|
||||
onError: (err) => {
|
||||
showToast(err.message, "error");
|
||||
},
|
||||
});
|
||||
|
||||
function toggleNoShow({
|
||||
attendee,
|
||||
bookingUid,
|
||||
}: {
|
||||
attendee: { email: string; noShow: boolean };
|
||||
bookingUid: string;
|
||||
}) {
|
||||
noShowMutation.mutate({ bookingUid, attendees: [attendee] });
|
||||
setNoShow(!noShow);
|
||||
}
|
||||
|
||||
return (
|
||||
<Dropdown open={openDropdown} onOpenChange={setOpenDropdown}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -978,29 +968,16 @@ const Attendee = (attendeeProps: AttendeeProps & NoShowProps) => {
|
||||
|
||||
{isBookingInPast && (
|
||||
<DropdownMenuItem className="focus:outline-none">
|
||||
{noShow ? (
|
||||
<DropdownItem
|
||||
data-testid="unmark-no-show"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setOpenDropdown(false);
|
||||
toggleNoShow({ attendee: { noShow: false, email }, bookingUid });
|
||||
}}
|
||||
StartIcon="eye">
|
||||
{t("unmark_as_no_show")}
|
||||
</DropdownItem>
|
||||
) : (
|
||||
<DropdownItem
|
||||
data-testid="mark-no-show"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setOpenDropdown(false);
|
||||
toggleNoShow({ attendee: { noShow: true, email }, bookingUid });
|
||||
}}
|
||||
StartIcon="eye-off">
|
||||
{t("mark_as_no_show")}
|
||||
</DropdownItem>
|
||||
)}
|
||||
<DropdownItem
|
||||
data-testid={noShow ? "unmark-no-show" : "mark-no-show"}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setOpenDropdown(false);
|
||||
noShowMutation.mutate({ bookingUid, attendees: [{ noShow: !noShow, email }] });
|
||||
}}
|
||||
StartIcon={noShow ? "eye" : "eye-off"}>
|
||||
{noShow ? t("unmark_as_no_show") : t("mark_as_no_show")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Schedule } from "@calcom/features/schedules";
|
||||
import { DEFAULT_SCHEDULE } from "@calcom/lib/availability";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
import { Button, Form } from "@calcom/ui";
|
||||
|
||||
import type { TRPCClientErrorLike } from "@trpc/client";
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useDebounce } from "@calcom/lib/hooks/useDebounce";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
import { Button, Dialog, DialogClose, DialogContent, DialogFooter, Input, Label } from "@calcom/ui";
|
||||
import { Icon } from "@calcom/ui";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { fetchUsername } from "@calcom/lib/fetchUsername";
|
||||
import { useDebounce } from "@calcom/lib/hooks/useDebounce";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
import { Button, Dialog, DialogClose, DialogContent, TextField, DialogFooter, Tooltip } from "@calcom/ui";
|
||||
import { Icon } from "@calcom/ui";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
|
||||
import { WEBSITE_URL, IS_SELF_HOSTED } from "@calcom/lib/constants";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
|
||||
import useRouterQuery from "@lib/hooks/useRouterQuery";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
import { z } from "zod";
|
||||
@@ -78,7 +78,7 @@ const getAppBySlug = async (appSlug: string) => {
|
||||
};
|
||||
|
||||
const getEventTypes = async (userId: number, teamIds?: number[]) => {
|
||||
const eventTypeSelect: Prisma.EventTypeSelect = {
|
||||
const eventTypeSelect = Prisma.validator<Prisma.EventTypeSelect>()({
|
||||
id: true,
|
||||
description: true,
|
||||
durationLimits: true,
|
||||
@@ -99,7 +99,7 @@ const getEventTypes = async (userId: number, teamIds?: number[]) => {
|
||||
userId: true,
|
||||
destinationCalendar: true,
|
||||
bookingFields: true,
|
||||
};
|
||||
});
|
||||
let eventTypeGroups: TEventTypeGroup[] | null = [];
|
||||
|
||||
if (teamIds && teamIds.length > 0) {
|
||||
|
||||
+202
-199
@@ -5,6 +5,8 @@ import { usePathname, useSearchParams } from "next/navigation";
|
||||
import Script from "next/script";
|
||||
import { useEffect, useState, useCallback, useMemo } from "react";
|
||||
|
||||
import { IS_PLAIN_CHAT_ENABLED } from "@calcom/lib/constants";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
Plain?: {
|
||||
@@ -75,228 +77,229 @@ interface PlainChatConfig {
|
||||
};
|
||||
}
|
||||
|
||||
const PlainChat = () => {
|
||||
const [config, setConfig] = useState<PlainChatConfig | null>(null);
|
||||
const [isSmallScreen, setIsSmallScreen] = useState(false);
|
||||
const { data: session } = useSession();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const PlainChat = IS_PLAIN_CHAT_ENABLED
|
||||
? () => {
|
||||
const [config, setConfig] = useState<PlainChatConfig | null>(null);
|
||||
const [isSmallScreen, setIsSmallScreen] = useState(false);
|
||||
const { data: session } = useSession();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const shouldOpenPlain = pathname === "/event-types" && searchParams?.has("openPlain");
|
||||
const userEmail = session?.user?.email;
|
||||
const shouldOpenPlain = pathname === "/event-types" && searchParams?.has("openPlain");
|
||||
const userEmail = session?.user?.email;
|
||||
|
||||
const isAppDomain = useMemo(() => {
|
||||
const restrictedPathsSet = new Set(
|
||||
(process.env.NEXT_PUBLIC_PLAIN_CHAT_EXCLUDED_PATHS?.split(",") || []).map((path) => path.trim())
|
||||
);
|
||||
const isAppDomain = useMemo(() => {
|
||||
const restrictedPathsSet = new Set(
|
||||
(process.env.NEXT_PUBLIC_PLAIN_CHAT_EXCLUDED_PATHS?.split(",") || []).map((path) => path.trim())
|
||||
);
|
||||
|
||||
const pathSegments = pathname?.split("/").filter(Boolean) || [];
|
||||
const pathSegments = pathname?.split("/").filter(Boolean) || [];
|
||||
|
||||
return (
|
||||
typeof window !== "undefined" &&
|
||||
window.location.origin === process.env.NEXT_PUBLIC_WEBAPP_URL &&
|
||||
!pathSegments.some((segment) => restrictedPathsSet.has(segment))
|
||||
);
|
||||
}, [pathname]);
|
||||
return (
|
||||
typeof window !== "undefined" &&
|
||||
window.location.origin === process.env.NEXT_PUBLIC_WEBAPP_URL &&
|
||||
!pathSegments.some((segment) => restrictedPathsSet.has(segment))
|
||||
);
|
||||
}, [pathname]);
|
||||
|
||||
const checkScreenSize = useCallback(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
const checkScreenSize = useCallback(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const isSmall = window.innerWidth < 768;
|
||||
setIsSmallScreen(isSmall);
|
||||
const isSmall = window.innerWidth < 768;
|
||||
setIsSmallScreen(isSmall);
|
||||
|
||||
if (isSmall && window.Plain) {
|
||||
const plainElement = document.querySelector("#plain-container");
|
||||
plainElement?.remove();
|
||||
window.Plain = undefined;
|
||||
} else if (!isSmall && window.Plain === undefined) {
|
||||
window.plainScriptLoaded?.();
|
||||
}
|
||||
}, []);
|
||||
if (isSmall && window.Plain) {
|
||||
const plainElement = document.querySelector("#plain-container");
|
||||
plainElement?.remove();
|
||||
window.Plain = undefined;
|
||||
} else if (!isSmall && window.Plain === undefined) {
|
||||
window.plainScriptLoaded?.();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const initConfig = useCallback(async () => {
|
||||
if (!userEmail) return;
|
||||
const initConfig = useCallback(async () => {
|
||||
if (!userEmail) return;
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/plain-hash", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
// Check if Plain Chat is enabled
|
||||
if (!IS_PLAIN_CHAT_ENABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Failed to generate hash: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.hash || !data.email || !data.appId) {
|
||||
throw new Error("Missing required fields in API response");
|
||||
}
|
||||
|
||||
const plainChatConfig: PlainChatConfig = {
|
||||
appId: data.appId,
|
||||
customerDetails: {
|
||||
email: data.email,
|
||||
shortName: data.shortName,
|
||||
fullName: data.fullName,
|
||||
emailHash: data.hash,
|
||||
chatAvatarUrl: data.chatAvatarUrl,
|
||||
},
|
||||
links: [
|
||||
{
|
||||
icon: "book",
|
||||
text: "Documentation",
|
||||
url: "https://cal.com/docs",
|
||||
},
|
||||
{
|
||||
icon: "chat",
|
||||
text: "Ask the community",
|
||||
url: "https://github.com/calcom/cal.com/discussions",
|
||||
},
|
||||
],
|
||||
chatButtons: [
|
||||
{
|
||||
icon: "chat",
|
||||
text: "Ask a question",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWNWAC464N8DZ6YE71YJRF"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
try {
|
||||
const response = await fetch("/api/plain-hash", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "bulb",
|
||||
text: "Send feedback",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWP3KECF1YQES6XF212RFW"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Failed to generate hash: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.hash || !data.email || !data.appId) {
|
||||
throw new Error("Missing required fields in API response");
|
||||
}
|
||||
|
||||
const plainChatConfig: PlainChatConfig = {
|
||||
appId: data.appId,
|
||||
customerDetails: {
|
||||
email: data.email,
|
||||
shortName: data.shortName,
|
||||
fullName: data.fullName,
|
||||
emailHash: data.hash,
|
||||
chatAvatarUrl: data.chatAvatarUrl,
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "error",
|
||||
text: "Report an issue",
|
||||
form: {
|
||||
fields: [
|
||||
{
|
||||
type: "dropdown",
|
||||
placeholder: "Select severity...",
|
||||
options: [
|
||||
links: [
|
||||
{
|
||||
icon: "book",
|
||||
text: "Documentation",
|
||||
url: "https://cal.com/docs",
|
||||
},
|
||||
{
|
||||
icon: "chat",
|
||||
text: "Ask the community",
|
||||
url: "https://github.com/calcom/cal.com/discussions",
|
||||
},
|
||||
],
|
||||
chatButtons: [
|
||||
{
|
||||
icon: "chat",
|
||||
text: "Ask a question",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWNWAC464N8DZ6YE71YJRF"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "bulb",
|
||||
text: "Send feedback",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWP3KECF1YQES6XF212RFW"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "error",
|
||||
text: "Report an issue",
|
||||
form: {
|
||||
fields: [
|
||||
{
|
||||
icon: "support",
|
||||
text: "I'm unable to use the app",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWNWAC464N8DZ6YE71YJRF"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
onClick: () => {
|
||||
console.log("User selected severity: Unable to use app");
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "error",
|
||||
text: "Major functionality degraded",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWP3KECF1YQES6XF212RFW"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
onClick: () => {
|
||||
console.log("User selected severity: Major functionality degraded");
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "bug",
|
||||
text: "Minor annoyance",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWPC8ADW0PK28JHMJR6NSS"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
onClick: () => {
|
||||
console.log("User selected severity: Minor annoyance");
|
||||
},
|
||||
type: "dropdown",
|
||||
placeholder: "Select severity...",
|
||||
options: [
|
||||
{
|
||||
icon: "support",
|
||||
text: "I'm unable to use the app",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWNWAC464N8DZ6YE71YJRF"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "error",
|
||||
text: "Major functionality degraded",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWP3KECF1YQES6XF212RFW"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: "bug",
|
||||
text: "Minor annoyance",
|
||||
threadDetails: {
|
||||
labelTypeIds: ["lt_01JFJWPC8ADW0PK28JHMJR6NSS"],
|
||||
tierIdentifier: { externalId: data.userTier },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
entryPoint: {
|
||||
type: "chat",
|
||||
},
|
||||
},
|
||||
],
|
||||
entryPoint: {
|
||||
type: "chat",
|
||||
},
|
||||
hideBranding: true,
|
||||
theme: "auto",
|
||||
style: {
|
||||
brandColor: "#FFFFFF",
|
||||
launcherBackgroundColor: "#262626",
|
||||
launcherIconColor: "#FFFFFF",
|
||||
},
|
||||
position: {
|
||||
zIndex: "1",
|
||||
bottom: "20px",
|
||||
right: "20px",
|
||||
},
|
||||
};
|
||||
hideBranding: true,
|
||||
theme: "auto",
|
||||
style: {
|
||||
brandColor: "#FFFFFF",
|
||||
launcherBackgroundColor: "#262626",
|
||||
launcherIconColor: "#FFFFFF",
|
||||
},
|
||||
position: {
|
||||
zIndex: "1",
|
||||
bottom: "20px",
|
||||
right: "20px",
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
|
||||
window.__PLAIN_CONFIG__ = plainChatConfig;
|
||||
}
|
||||
|
||||
setConfig(plainChatConfig);
|
||||
|
||||
if (shouldOpenPlain) {
|
||||
const timer = setTimeout(() => {
|
||||
if (window.Plain) {
|
||||
window.Plain.open();
|
||||
if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
|
||||
window.__PLAIN_CONFIG__ = plainChatConfig;
|
||||
}
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize Plain Chat:", error);
|
||||
}
|
||||
}, [userEmail, shouldOpenPlain]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAppDomain) return;
|
||||
setConfig(plainChatConfig);
|
||||
|
||||
checkScreenSize();
|
||||
window.addEventListener("resize", checkScreenSize);
|
||||
initConfig();
|
||||
|
||||
return () => window.removeEventListener("resize", checkScreenSize);
|
||||
}, [isAppDomain, checkScreenSize, initConfig, userEmail]);
|
||||
|
||||
const plainChatScript = `
|
||||
window.plainScriptLoaded = function() {
|
||||
if (window.Plain && ${Boolean(config)}) {
|
||||
try {
|
||||
Plain.init(${config ? JSON.stringify(config) : null});
|
||||
if (shouldOpenPlain) {
|
||||
const timer = setTimeout(() => {
|
||||
if (window.Plain) {
|
||||
window.Plain.open();
|
||||
}
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize Plain:", error);
|
||||
console.error("Failed to initialize Plain Chat:", error);
|
||||
}
|
||||
}
|
||||
}, [userEmail, shouldOpenPlain]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAppDomain) return;
|
||||
|
||||
// Skip initialization if Plain Chat is not enabled
|
||||
if (!IS_PLAIN_CHAT_ENABLED) return;
|
||||
|
||||
checkScreenSize();
|
||||
window.addEventListener("resize", checkScreenSize);
|
||||
initConfig();
|
||||
|
||||
return () => window.removeEventListener("resize", checkScreenSize);
|
||||
}, [isAppDomain, checkScreenSize, initConfig, userEmail]);
|
||||
|
||||
const plainChatScript = `
|
||||
window.plainScriptLoaded = function() {
|
||||
if (window.Plain && ${Boolean(config)}) {
|
||||
try {
|
||||
Plain.init(${config ? JSON.stringify(config) : null});
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize Plain:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
if (!isAppDomain || isSmallScreen || !config || typeof window === "undefined") return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Script
|
||||
id="plain-chat"
|
||||
src="https://chat.cdn-plain.com/index.js"
|
||||
strategy="afterInteractive"
|
||||
onLoad={() => window.plainScriptLoaded?.()}
|
||||
/>
|
||||
<Script
|
||||
id="plain-chat-init"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{ __html: plainChatScript }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
if (!isAppDomain || isSmallScreen || !config || typeof window === "undefined") return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Script
|
||||
id="plain-chat"
|
||||
src="https://chat.cdn-plain.com/index.js"
|
||||
strategy="afterInteractive"
|
||||
onLoad={() => window.plainScriptLoaded?.()}
|
||||
/>
|
||||
<Script
|
||||
id="plain-chat-init"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{ __html: plainChatScript }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
: () => null;
|
||||
|
||||
export default PlainChat;
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import type { GetServerSidePropsResult } from "next";
|
||||
|
||||
import { getFeatureFlag } from "@calcom/features/flags/server/utils";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const prisma = await import("@calcom/prisma").then((mod) => mod.default);
|
||||
export const getServerSideProps = async (): Promise<GetServerSidePropsResult<{ isOrg: boolean }>> => {
|
||||
const organizations = await getFeatureFlag(prisma, "organizations");
|
||||
// Check if organizations are enabled
|
||||
if (!organizations) {
|
||||
return {
|
||||
notFound: true,
|
||||
} as const;
|
||||
};
|
||||
}
|
||||
|
||||
const querySlug = context.query.slug as string;
|
||||
|
||||
return {
|
||||
props: {
|
||||
querySlug: querySlug ?? null,
|
||||
isOrg: true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { debounce } from "lodash";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
|
||||
// Dynamically adjusts DataTable height on mobile to prevent nested scrolling
|
||||
// and ensure the table fits within the viewport without overflowing (hacky)
|
||||
export function useStretchedHeightToBottom(ref: React.RefObject<HTMLDivElement>) {
|
||||
const lastOffsetY = useRef<number>();
|
||||
const lastWindowHeight = useRef<number>();
|
||||
const BOTTOM_NAV_HEIGHT = 64;
|
||||
const BUFFER = 32;
|
||||
|
||||
const updateHeight = useCallback(
|
||||
debounce(() => {
|
||||
if (!ref.current) return;
|
||||
const rect = ref.current.getBoundingClientRect();
|
||||
if (rect.top !== lastOffsetY.current || window.innerHeight !== lastWindowHeight.current) {
|
||||
lastOffsetY.current = rect.top;
|
||||
lastWindowHeight.current = window.innerHeight;
|
||||
let height = window.innerHeight - lastOffsetY.current - BUFFER;
|
||||
if (window.innerWidth < 640) {
|
||||
height = height - BOTTOM_NAV_HEIGHT;
|
||||
}
|
||||
ref.current.style.height = `${height}px`;
|
||||
}
|
||||
}, 200),
|
||||
[ref.current]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
updateHeight();
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, [updateHeight]);
|
||||
|
||||
updateHeight();
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
useReactTable,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getSortedRowModel,
|
||||
createColumnHelper,
|
||||
} from "@tanstack/react-table";
|
||||
import { useReactTable, getCoreRowModel, getSortedRowModel, createColumnHelper } from "@tanstack/react-table";
|
||||
import { useMemo, useRef } from "react";
|
||||
|
||||
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import {
|
||||
useDataTable,
|
||||
DataTableProvider,
|
||||
DataTableWrapper,
|
||||
DataTableFilters,
|
||||
@@ -33,7 +28,6 @@ import BookingListItem from "@components/booking/BookingListItem";
|
||||
import SkeletonLoader from "@components/booking/SkeletonLoader";
|
||||
|
||||
import { useFacetedUniqueValues } from "~/bookings/hooks/useFacetedUniqueValues";
|
||||
import { useStretchedHeightToBottom } from "~/bookings/hooks/useStretchedHeightToBottom";
|
||||
import type { validStatuses } from "~/bookings/lib/validStatuses";
|
||||
|
||||
type BookingListingStatus = (typeof validStatuses)[number];
|
||||
@@ -109,7 +103,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
const { t } = useLocale();
|
||||
const user = useMeQuery().data;
|
||||
const tableContainerRef = useRef<HTMLDivElement>(null);
|
||||
useStretchedHeightToBottom(tableContainerRef);
|
||||
|
||||
const eventTypeIds = useFilterValue("eventTypeId", ZMultiSelectFilterValue)?.data as number[] | undefined;
|
||||
const teamIds = useFilterValue("teamId", ZMultiSelectFilterValue)?.data as number[] | undefined;
|
||||
@@ -118,26 +111,24 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
const attendeeName = useFilterValue("attendeeName", ZTextFilterValue);
|
||||
const attendeeEmail = useFilterValue("attendeeEmail", ZTextFilterValue);
|
||||
|
||||
const query = trpc.viewer.bookings.get.useInfiniteQuery(
|
||||
{
|
||||
limit: 10,
|
||||
filters: {
|
||||
status,
|
||||
eventTypeIds,
|
||||
teamIds,
|
||||
userIds,
|
||||
attendeeName,
|
||||
attendeeEmail,
|
||||
afterStartDate: dateRange?.startDate
|
||||
? dayjs(dateRange?.startDate).startOf("day").toISOString()
|
||||
: undefined,
|
||||
beforeEndDate: dateRange?.endDate ? dayjs(dateRange?.endDate).endOf("day").toISOString() : undefined,
|
||||
},
|
||||
const { limit, offset } = useDataTable();
|
||||
|
||||
const query = trpc.viewer.bookings.get.useQuery({
|
||||
limit,
|
||||
offset,
|
||||
filters: {
|
||||
status,
|
||||
eventTypeIds,
|
||||
teamIds,
|
||||
userIds,
|
||||
attendeeName,
|
||||
attendeeEmail,
|
||||
afterStartDate: dateRange?.startDate
|
||||
? dayjs(dateRange?.startDate).startOf("day").toISOString()
|
||||
: undefined,
|
||||
beforeEndDate: dateRange?.endDate ? dayjs(dateRange?.endDate).endOf("day").toISOString() : undefined,
|
||||
},
|
||||
{
|
||||
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const columns = useMemo(() => {
|
||||
const columnHelper = createColumnHelper<RowData>();
|
||||
@@ -149,7 +140,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.MULTI_SELECT,
|
||||
@@ -162,7 +152,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.MULTI_SELECT,
|
||||
@@ -175,7 +164,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.MULTI_SELECT,
|
||||
@@ -188,7 +176,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.TEXT,
|
||||
@@ -201,7 +188,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.TEXT,
|
||||
@@ -214,7 +200,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
enableColumnFilter: true,
|
||||
enableSorting: false,
|
||||
cell: () => null,
|
||||
filterFn: () => true,
|
||||
meta: {
|
||||
filter: {
|
||||
type: ColumnFilterType.DATE_RANGE,
|
||||
@@ -262,7 +247,7 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
];
|
||||
}, [user, status, t]);
|
||||
|
||||
const isEmpty = useMemo(() => !query.data?.pages[0]?.bookings.length, [query.data]);
|
||||
const isEmpty = useMemo(() => !query.data?.bookings.length, [query.data]);
|
||||
|
||||
const flatData = useMemo<RowData[]>(() => {
|
||||
const shownBookings: Record<string, BookingOutput[]> = {};
|
||||
@@ -289,37 +274,33 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
query.data?.pages.flatMap((page) =>
|
||||
page.bookings.filter(filterBookings).map((booking) => ({
|
||||
type: "data",
|
||||
booking,
|
||||
recurringInfo: page.recurringInfo.find(
|
||||
(info) => info.recurringEventId === booking.recurringEventId
|
||||
),
|
||||
isToday: false,
|
||||
}))
|
||||
) || []
|
||||
query.data?.bookings.filter(filterBookings).map((booking) => ({
|
||||
type: "data",
|
||||
booking,
|
||||
recurringInfo: query.data?.recurringInfo.find(
|
||||
(info) => info.recurringEventId === booking.recurringEventId
|
||||
),
|
||||
isToday: false,
|
||||
})) || []
|
||||
);
|
||||
}, [query.data]);
|
||||
|
||||
const bookingsToday = useMemo<RowData[]>(() => {
|
||||
return (
|
||||
query.data?.pages.flatMap((page) =>
|
||||
page.bookings
|
||||
.filter(
|
||||
(booking: BookingOutput) =>
|
||||
dayjs(booking.startTime).tz(user?.timeZone).format("YYYY-MM-DD") ===
|
||||
dayjs().tz(user?.timeZone).format("YYYY-MM-DD")
|
||||
)
|
||||
.map((booking) => ({
|
||||
type: "data" as const,
|
||||
booking,
|
||||
recurringInfo: page.recurringInfo.find(
|
||||
(info) => info.recurringEventId === booking.recurringEventId
|
||||
),
|
||||
isToday: true,
|
||||
}))
|
||||
) || []
|
||||
query.data?.bookings
|
||||
.filter(
|
||||
(booking: BookingOutput) =>
|
||||
dayjs(booking.startTime).tz(user?.timeZone).format("YYYY-MM-DD") ===
|
||||
dayjs().tz(user?.timeZone).format("YYYY-MM-DD")
|
||||
)
|
||||
.map((booking) => ({
|
||||
type: "data" as const,
|
||||
booking,
|
||||
recurringInfo: query.data?.recurringInfo.find(
|
||||
(info) => info.recurringEventId === booking.recurringEventId
|
||||
),
|
||||
isToday: true,
|
||||
})) ?? []
|
||||
);
|
||||
}, [query.data]);
|
||||
|
||||
@@ -353,7 +334,6 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
},
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFacetedUniqueValues,
|
||||
});
|
||||
@@ -379,17 +359,16 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
||||
)}
|
||||
<DataTableWrapper
|
||||
className="mb-6"
|
||||
tableContainerRef={tableContainerRef}
|
||||
table={table}
|
||||
testId={`${status}-bookings`}
|
||||
bodyTestId="bookings"
|
||||
hideHeader={true}
|
||||
headerClassName="hidden"
|
||||
isPending={query.isPending}
|
||||
hasNextPage={query.hasNextPage}
|
||||
fetchNextPage={query.fetchNextPage}
|
||||
isFetching={query.isFetching}
|
||||
totalRowCount={query.data?.totalCount}
|
||||
variant="compact"
|
||||
paginationMode="infinite"
|
||||
paginationMode="standard"
|
||||
ToolbarLeft={
|
||||
<>
|
||||
<DataTableFilters.AddFilterButton table={table} hideWhenFilterApplied />
|
||||
|
||||
@@ -310,12 +310,14 @@ export default function Success(props: PageProps) {
|
||||
const host = bookingInfo.user.name || bookingInfo.user.email;
|
||||
if (isHost) {
|
||||
return t(`${titlePrefix}emailed_host_and_attendee${titleSuffix}`, {
|
||||
user: attendee,
|
||||
host,
|
||||
attendee,
|
||||
});
|
||||
}
|
||||
if (isAttendee) {
|
||||
return t(`${titlePrefix}emailed_host_and_attendee${titleSuffix}`, {
|
||||
user: host,
|
||||
host,
|
||||
attendee,
|
||||
});
|
||||
}
|
||||
return t(`${titlePrefix}emailed_host_and_attendee${titleSuffix}`, {
|
||||
|
||||
@@ -21,7 +21,7 @@ import turndown from "@calcom/lib/turndownService";
|
||||
import { IdentityProvider } from "@calcom/prisma/enums";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import type { AppRouter } from "@calcom/trpc/types/server/routers/_app";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import AddNewTeamMembers from "@calcom/features/ee/teams/components/AddNewTeamMembers";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const router = useRouter();
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const query = useCompatSearchParams();
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
currentStep={4}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
router.push(`/settings/organizations/${query.get("id")}/add-teams`);
|
||||
}}>
|
||||
{children}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
const OrgAddNewTeamMembers = () => <AddNewTeamMembers isOrg={true} />;
|
||||
export default OrgAddNewTeamMembers;
|
||||
+78
-88
@@ -1,24 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFieldArray, useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
||||
import { IS_TEAM_BILLING_ENABLED_CLIENT } from "@calcom/lib/constants";
|
||||
import { useOnboarding } from "@calcom/features/ee/organizations/lib/onboardingStore";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { useRouterQuery } from "@calcom/lib/hooks/useRouterQuery";
|
||||
import { CreationSource } from "@calcom/prisma/enums";
|
||||
import { UserPermissionRole } from "@calcom/prisma/enums";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, CheckboxField, Form, Icon, showToast, TextField } from "@calcom/ui";
|
||||
import {
|
||||
Button,
|
||||
CheckboxField,
|
||||
Form,
|
||||
Icon,
|
||||
TextField,
|
||||
SkeletonText,
|
||||
SkeletonContainer,
|
||||
SkeletonButton,
|
||||
} from "@calcom/ui";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
const querySchema = z.object({
|
||||
id: z.string().transform((val) => parseInt(val)),
|
||||
});
|
||||
|
||||
const schema = z.object({
|
||||
teams: z.array(
|
||||
z.object({
|
||||
@@ -35,44 +36,58 @@ const schema = z.object({
|
||||
});
|
||||
|
||||
export const AddNewTeamsForm = () => {
|
||||
const { data: teams } = trpc.viewer.teams.list.useQuery();
|
||||
const routerQuery = useRouterQuery();
|
||||
const { data: teams, isLoading } = trpc.viewer.teams.listOwnedTeams.useQuery();
|
||||
|
||||
const { id: orgId } = querySchema.parse(routerQuery);
|
||||
|
||||
const { data: org } = trpc.viewer.teams.get.useQuery({ teamId: orgId, isOrg: true });
|
||||
|
||||
if (!teams || !org) {
|
||||
return null;
|
||||
if (isLoading) {
|
||||
return (
|
||||
<SkeletonContainer as="div" className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<SkeletonText className="h-4 w-32" />
|
||||
<div className="space-y-2">
|
||||
{[...Array(2)].map((_, i) => (
|
||||
<div key={i} className="flex items-center space-x-2">
|
||||
<SkeletonText className="h-5 w-5" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<SkeletonText className="h-4 w-32" />
|
||||
<div className="space-y-2">
|
||||
{[...Array(3)].map((_, i) => (
|
||||
<SkeletonText key={i} className="h-10 w-full" />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<SkeletonButton className="w-full" />
|
||||
</SkeletonContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const orgWithRequestedSlug = {
|
||||
...org,
|
||||
requestedSlug: org.metadata.requestedSlug ?? null,
|
||||
};
|
||||
|
||||
const regularTeams = teams.filter((team) => !team.parentId);
|
||||
return <AddNewTeamsFormChild org={orgWithRequestedSlug} teams={regularTeams} />;
|
||||
return <AddNewTeamsFormChild teams={(teams ?? []).map(({ id, name, slug }) => ({ id, name, slug }))} />;
|
||||
};
|
||||
|
||||
const AddNewTeamsFormChild = ({
|
||||
teams,
|
||||
org,
|
||||
}: {
|
||||
org: { id: number; slug: string | null; requestedSlug: string | null };
|
||||
teams: { id: number; name: string; slug: string | null }[];
|
||||
}) => {
|
||||
const AddNewTeamsFormChild = ({ teams }: { teams: { id: number; name: string; slug: string | null }[] }) => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const [counter, setCounter] = useState(1);
|
||||
const { useOnboardingStore } = useOnboarding();
|
||||
const { slug: orgSlug, setTeams, teams: teamsFromStore } = useOnboardingStore();
|
||||
const teamsToCreateFromStore = teamsFromStore.filter((team) => !team.isBeingMigrated);
|
||||
const teamsToMigrateFromStore = teamsFromStore.filter((team) => team.isBeingMigrated);
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
teams: [{ name: "" }],
|
||||
moveTeams: teams.map((team) => ({
|
||||
id: team.id,
|
||||
shouldMove: false,
|
||||
newSlug: getSuggestedSlug({ teamSlug: team.slug, orgSlug: org.slug || org.requestedSlug }),
|
||||
})),
|
||||
teams: teamsToCreateFromStore.length ? teamsToCreateFromStore : [{ name: "" }],
|
||||
moveTeams: teams.map((team) => {
|
||||
const teamToMigrateInStore = teamsToMigrateFromStore.find((t) => t.id === team.id);
|
||||
return {
|
||||
id: team.id,
|
||||
shouldMove: !!teamToMigrateInStore,
|
||||
newSlug: teamToMigrateInStore?.slug || getSuggestedSlug({ teamSlug: team.slug, orgSlug }),
|
||||
name: team.name,
|
||||
};
|
||||
}),
|
||||
}, // Set initial values
|
||||
resolver: async (data) => {
|
||||
try {
|
||||
@@ -91,27 +106,12 @@ const AddNewTeamsFormChild = ({
|
||||
}
|
||||
},
|
||||
});
|
||||
const session = useSession();
|
||||
const isAdmin =
|
||||
session.data?.user?.role === UserPermissionRole.ADMIN ||
|
||||
session.data?.user?.impersonatedBy?.role === UserPermissionRole.ADMIN;
|
||||
|
||||
const allowWizardCompletionWithoutUpgrading = !IS_TEAM_BILLING_ENABLED_CLIENT || isAdmin;
|
||||
const { register, control, watch, getValues } = form;
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
control,
|
||||
name: "teams",
|
||||
});
|
||||
|
||||
const publishOrgMutation = trpc.viewer.organizations.publish.useMutation({
|
||||
onSuccess(data) {
|
||||
router.push(data.url);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(error.message, "error");
|
||||
},
|
||||
});
|
||||
|
||||
const handleCounterIncrease = () => {
|
||||
if (counter >= 0 && counter < 5) {
|
||||
setCounter((prevCounter) => prevCounter + 1);
|
||||
@@ -124,40 +124,32 @@ const AddNewTeamsFormChild = ({
|
||||
setCounter((prevCounter) => prevCounter - 1);
|
||||
};
|
||||
|
||||
const createTeamsMutation = trpc.viewer.organizations.createTeams.useMutation({
|
||||
async onSuccess(data) {
|
||||
if (data.duplicatedSlugs.length) {
|
||||
showToast(t("duplicated_slugs_warning", { slugs: data.duplicatedSlugs.join(", ") }), "warning");
|
||||
// Server will return array of duplicated slugs, so we need to wait for user to read the warning
|
||||
// before pushing to next page
|
||||
setTimeout(() => handleSuccessRedirect, 3000);
|
||||
} else {
|
||||
handleSuccessRedirect();
|
||||
}
|
||||
|
||||
function handleSuccessRedirect() {
|
||||
if (allowWizardCompletionWithoutUpgrading) {
|
||||
router.push(`/event-types`);
|
||||
return;
|
||||
}
|
||||
// mutate onSuccess will take care of routing to the correct place.
|
||||
publishOrgMutation.mutate();
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(t(error.message), "error");
|
||||
},
|
||||
});
|
||||
|
||||
const handleFormSubmit = () => {
|
||||
const fields = getValues("teams");
|
||||
const moveTeams = getValues("moveTeams");
|
||||
createTeamsMutation.mutate({
|
||||
orgId: org.id,
|
||||
moveTeams,
|
||||
teamNames: fields.map((field) => field.name),
|
||||
creationSource: CreationSource.WEBAPP,
|
||||
|
||||
const teamsBeingMoved = moveTeams.map((team) => {
|
||||
return {
|
||||
id: team.id,
|
||||
isBeingMigrated: team.shouldMove,
|
||||
slug: team.newSlug,
|
||||
name: team.name,
|
||||
};
|
||||
});
|
||||
|
||||
const newTeams = fields
|
||||
.map((team) => {
|
||||
return {
|
||||
id: -1,
|
||||
isBeingMigrated: false,
|
||||
slug: getSuggestedSlug({ teamSlug: team.name, orgSlug }),
|
||||
name: team.name,
|
||||
};
|
||||
})
|
||||
.filter((team) => team.slug !== "");
|
||||
|
||||
setTeams([...teamsBeingMoved, ...newTeams]);
|
||||
router.push(`/settings/organizations/new/onboard-members`);
|
||||
};
|
||||
|
||||
const moveTeams = watch("moveTeams");
|
||||
@@ -233,7 +225,6 @@ const AddNewTeamsFormChild = ({
|
||||
<Button
|
||||
StartIcon="plus"
|
||||
color="secondary"
|
||||
disabled={createTeamsMutation.isPending}
|
||||
onClick={handleCounterIncrease}
|
||||
aria-label={t("add_a_team")}
|
||||
className="my-1"
|
||||
@@ -243,12 +234,11 @@ const AddNewTeamsFormChild = ({
|
||||
)}
|
||||
<Button
|
||||
EndIcon="arrow-right"
|
||||
type="submit"
|
||||
color="primary"
|
||||
className="mt-6 w-full justify-center"
|
||||
data-testId="continue_or_checkout"
|
||||
disabled={createTeamsMutation.isPending || createTeamsMutation.isSuccess}
|
||||
onClick={handleFormSubmit}>
|
||||
{allowWizardCompletionWithoutUpgrading ? t("continue") : t("checkout")}
|
||||
data-testId="continue_or_checkout">
|
||||
{t("continue")}
|
||||
</Button>
|
||||
</Form>
|
||||
</>
|
||||
@@ -0,0 +1,213 @@
|
||||
"use client";
|
||||
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useOnboarding } from "@calcom/features/ee/organizations/lib/onboardingStore";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
SkeletonContainer,
|
||||
SkeletonText,
|
||||
SkeletonButton,
|
||||
Tooltip,
|
||||
TextField,
|
||||
showToast,
|
||||
Alert,
|
||||
} from "@calcom/ui";
|
||||
|
||||
type TeamMember = RouterOutputs["viewer"]["teams"]["listMembers"]["members"][number];
|
||||
|
||||
const AddNewTeamMembers = () => {
|
||||
const session = useSession();
|
||||
|
||||
if (session.status === "loading") {
|
||||
return <SkeletonContainer>Loading...</SkeletonContainer>;
|
||||
}
|
||||
return <AddNewTeamMembersForm />;
|
||||
};
|
||||
|
||||
const useCheckout = () => {
|
||||
const { t } = useLocale();
|
||||
const [serverErrorMessage, setServerErrorMessage] = useState("");
|
||||
const mutation = trpc.viewer.organizations.createWithPaymentIntent.useMutation({
|
||||
onSuccess: (data) => {
|
||||
if (data.checkoutUrl) {
|
||||
window.location.href = data.checkoutUrl;
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
setServerErrorMessage(t(error.message));
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
mutation,
|
||||
mutate: mutation.mutate,
|
||||
isPending: mutation.isPending,
|
||||
errorMessage: serverErrorMessage,
|
||||
};
|
||||
};
|
||||
|
||||
export const AddNewTeamMembersForm = () => {
|
||||
const { t } = useLocale();
|
||||
const { useOnboardingStore } = useOnboarding();
|
||||
const {
|
||||
addInvitedMember,
|
||||
removeInvitedMember,
|
||||
orgOwnerEmail,
|
||||
teams,
|
||||
invitedMembers,
|
||||
logo,
|
||||
bio,
|
||||
onboardingId,
|
||||
} = useOnboardingStore();
|
||||
const checkout = useCheckout();
|
||||
|
||||
const teamIds = teams.filter((team) => team.isBeingMigrated && team.id > 0).map((team) => team.id);
|
||||
|
||||
const results = trpc.useQueries((t) => teamIds.map((teamId) => t.viewer.teams.listMembers({ teamId })));
|
||||
|
||||
const isLoading = results.some((result) => result.isLoading);
|
||||
|
||||
// Combine all members and remove duplicates
|
||||
const uniqueMembers = results
|
||||
.reduce<TeamMember[]>((acc, result) => {
|
||||
if (result.data?.members) {
|
||||
return [...acc, ...result.data.members];
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.filter((member, index, self) => index === self.findIndex((m) => m.email === member.email));
|
||||
|
||||
const { register, handleSubmit, reset } = useForm<{ email: string }>();
|
||||
|
||||
const onSubmit = handleSubmit((data) => {
|
||||
const parsedEmail = z.string().email().safeParse(data.email);
|
||||
if (!parsedEmail.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedEmail = parsedEmail.data.toLowerCase();
|
||||
|
||||
// Check if email exists in either invitedMembers or uniqueMembers
|
||||
const isInvited = invitedMembers.some((member) => member.email.toLowerCase() === normalizedEmail);
|
||||
const isExisting = uniqueMembers?.some((member) => member.email.toLowerCase() === normalizedEmail);
|
||||
|
||||
if (isInvited || isExisting) {
|
||||
showToast(t("member_already_invited"), "error");
|
||||
return;
|
||||
}
|
||||
|
||||
addInvitedMember({ email: normalizedEmail });
|
||||
reset();
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<SkeletonContainer as="div" className="space-y-6">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonButton className="mr-6 h-8 w-20 rounded-md p-5" />
|
||||
</SkeletonContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{checkout.errorMessage && (
|
||||
<div className="mb-4">
|
||||
<Alert severity="error" message={checkout.errorMessage} />
|
||||
</div>
|
||||
)}
|
||||
<div className="space-y-6">
|
||||
<div className="flex space-x-3">
|
||||
<form onSubmit={onSubmit} className="flex w-full items-end space-x-2">
|
||||
<div className="flex-grow">
|
||||
<TextField
|
||||
label={t("email")}
|
||||
type="email"
|
||||
{...register("email", { required: true })}
|
||||
placeholder="colleague@company.com"
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" StartIcon="plus" color="secondary">
|
||||
{t("add")}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{(invitedMembers.length > 0 || uniqueMembers?.length > 0) && (
|
||||
<ul
|
||||
className="border-subtle divide-subtle max-h-[300px] divide-y overflow-y-auto rounded-md border"
|
||||
data-testid="pending-member-list">
|
||||
{invitedMembers.map((member) => (
|
||||
<li key={member.email} className="flex items-center justify-between px-5 py-2">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Avatar size="sm" alt={member.email} />
|
||||
<div className="flex gap-1">
|
||||
<Tooltip content={member.email}>
|
||||
<span className="text-subtle max-w-[250px] truncate text-sm">{member.email}</span>
|
||||
</Tooltip>
|
||||
<Badge variant="gray">{t("pending")}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="icon"
|
||||
size="sm"
|
||||
color="minimal"
|
||||
StartIcon="x"
|
||||
onClick={() => removeInvitedMember(member.email)}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
{uniqueMembers?.map((member) => (
|
||||
<li key={member.email} className="flex items-center justify-between px-5 py-2">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Avatar size="sm" alt={member.email} imageSrc={member.avatarUrl} />
|
||||
<div className="flex gap-1">
|
||||
<Tooltip content={member.email}>
|
||||
<span className="text-emphasis text-sm font-medium">{member.name || member.email}</span>
|
||||
</Tooltip>
|
||||
{/* TODO: We should show the team name here instead of "migrating from team" */}
|
||||
<Badge variant="green">{t("migrating_from_team")}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-3 mt-6 flex items-center justify-end">
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (!onboardingId) {
|
||||
console.error("Org owner email and onboardingId are required", {
|
||||
orgOwnerEmail,
|
||||
onboardingId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
checkout.mutation.mutate({
|
||||
logo,
|
||||
bio,
|
||||
teams,
|
||||
invitedMembers,
|
||||
onboardingId,
|
||||
});
|
||||
}}
|
||||
loading={checkout.isPending}>
|
||||
{t("checkout")}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddNewTeamMembers;
|
||||
@@ -0,0 +1,67 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useOnboarding } from "@calcom/features/ee/organizations/lib/onboardingStore";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
import { Button, Icon } from "@calcom/ui";
|
||||
|
||||
const PaymentStatusView = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const paymentStatus = searchParams?.get("paymentStatus");
|
||||
const paymentError = searchParams?.get("error");
|
||||
const { useOnboardingStore } = useOnboarding({
|
||||
step: "status",
|
||||
});
|
||||
const [organizationCreated, setOrganizationCreated] = useState<boolean>(false);
|
||||
const { name } = useOnboardingStore();
|
||||
|
||||
const { data: organization } = trpc.viewer.organizations.listCurrent.useQuery(undefined, {
|
||||
refetchInterval: 2000, // Poll every 2 seconds until org is created
|
||||
enabled: !organizationCreated,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (organization) {
|
||||
setOrganizationCreated(true);
|
||||
// Organization is created, redirect to next step
|
||||
router.push(`/settings/organizations`);
|
||||
}
|
||||
}, [organization, router, useOnboardingStore]);
|
||||
|
||||
if (paymentStatus === "failed" || paymentError) {
|
||||
return (
|
||||
<div className="flex min-h-[500px] flex-col items-center justify-center space-y-6 px-4 sm:px-6">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
|
||||
<Icon name="x" className="h-6 w-6 text-red-600" />
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h1 className="font-cal text-emphasis text-2xl">{t("payment_failed")}</h1>
|
||||
<p className="text-default mt-2 text-sm">{paymentError || t("payment_failed_description")}</p>
|
||||
</div>
|
||||
<Button color="secondary" href="/settings/organizations/new/onboard-members">
|
||||
{t("try_again")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[500px] flex-col items-center justify-center space-y-6 px-4 sm:px-6">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
|
||||
<Icon name="check" className="h-6 w-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<h1 className="font-cal text-emphasis text-2xl">{t("payment_successful")}</h1>
|
||||
<p className="text-default mt-2 text-sm">{t("creating_your_organization", { orgName: name })}</p>
|
||||
<p className="text-subtle mt-1 text-sm">{t("this_may_take_a_few_seconds")}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PaymentStatusView;
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<WizardLayout currentStep={3} maxSteps={5}>
|
||||
<WizardLayout currentStep={2} maxSteps={5}>
|
||||
{children}
|
||||
</WizardLayout>
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
import { AddNewTeamsForm } from "./_components/AddNewTeamsForm";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<WizardLayout currentStep={3} maxSteps={5}>
|
||||
{children}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddNewTeamsForm;
|
||||
@@ -0,0 +1,39 @@
|
||||
graph TD
|
||||
Start[Start] --> AboutOrg[About Organization Form]
|
||||
AboutOrg -->|Set Name, Logo, Bio| Teams[Add Teams]
|
||||
Teams -->|Create/Migrate Teams| Members[Add Team Members]
|
||||
Members -->|Add Members & Invite| Payment[Payment]
|
||||
Payment -->|Create Payment Intent| StripeCheckout[Stripe Checkout]
|
||||
StripeCheckout -->|Success| PaymentSuccess[Payment Success View]
|
||||
StripeCheckout -->|Failure| Payment
|
||||
|
||||
subgraph "About Organization"
|
||||
AboutOrg -->|Store in onboardingStore| OrgData[Organization Data]
|
||||
OrgData -->|"Name, Logo, Bio"| ValidateSlug[Validate Slug]
|
||||
end
|
||||
|
||||
subgraph "Teams Setup"
|
||||
Teams -->|Store in onboardingStore| TeamData[Teams Data]
|
||||
TeamData -->|"Create New/Migrate"| TeamMembers[Team Members]
|
||||
end
|
||||
|
||||
subgraph "Members Setup"
|
||||
Members -->|Store in onboardingStore| MemberData[Members Data]
|
||||
MemberData -->|"Invited/Migrating"| MembersList[Members List]
|
||||
end
|
||||
|
||||
subgraph "Payment Process"
|
||||
Payment -->|Create Intent| PaymentData[Payment Data]
|
||||
PaymentData -->|"Billing Period, Price/Seat"| StripeSession[Stripe Session]
|
||||
end
|
||||
|
||||
subgraph "Webhook Handling"
|
||||
StripeCheckout -->|invoice.paid| WebhookHandler[Webhook Handler]
|
||||
WebhookHandler -->|Process Payment| OrgCreation[Create Organization]
|
||||
OrgCreation --> Complete[Complete]
|
||||
end
|
||||
|
||||
style Start fill:#f9f,stroke:#333,stroke-width:2px
|
||||
style Complete fill:#9f9,stroke:#333,stroke-width:2px
|
||||
style StripeCheckout fill:#fdd,stroke:#333,stroke-width:2px
|
||||
style WebhookHandler fill:#ddf,stroke:#333,stroke-width:2px
|
||||
@@ -0,0 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
import AddNewTeamMembers from "./_components/OnboardMembersView";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<WizardLayout currentStep={4} maxSteps={5}>
|
||||
{children}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddNewTeamMembers;
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { AdminOnboardingHandover } from "@calcom/features/ee/organizations/components";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<WizardLayout currentStep={2} maxSteps={2}>
|
||||
{children}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminOnboardingHandover;
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { AddNewTeamsForm } from "@calcom/features/ee/organizations/components";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
import PaymentStatusView from "~/settings/organizations/new/_components/PaymentStatusView";
|
||||
|
||||
export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<WizardLayout currentStep={5} maxSteps={5}>
|
||||
@@ -11,4 +12,4 @@ export const LayoutWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AddNewTeamsForm;
|
||||
export default PaymentStatusView;
|
||||
@@ -535,6 +535,11 @@ const nextConfig = {
|
||||
},
|
||||
async redirects() {
|
||||
const redirects = [
|
||||
{
|
||||
source: "/settings/organizations",
|
||||
destination: "/settings/organizations/profile",
|
||||
permanent: false,
|
||||
},
|
||||
{
|
||||
source: "/apps/routing-forms",
|
||||
destination: "/routing/forms",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@calcom/web",
|
||||
"version": "5.0.18",
|
||||
"version": "5.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"analyze": "ANALYZE=true next build",
|
||||
@@ -20,7 +20,8 @@
|
||||
"lint:fix": "eslint . --ext .ts,.js,.tsx,.jsx --fix",
|
||||
"lint:report": "eslint . --format json --output-file ../../lint-results/web.json",
|
||||
"check-changed-files": "ts-node scripts/ts-check-changed-files.ts",
|
||||
"translate-locales": "ts-node scripts/check-missing-translations.ts"
|
||||
"translate-locales": "ts-node scripts/check-missing-translations.ts",
|
||||
"stripe:listen": "stripe listen --forward-to http://localhost:3000/api/stripe/webhook"
|
||||
},
|
||||
"engines": {
|
||||
"yarn": "3.4.1"
|
||||
|
||||
@@ -11,7 +11,6 @@ import type { createEmailsFixture } from "../fixtures/emails";
|
||||
import { test } from "../lib/fixtures";
|
||||
import { fillStripeTestCheckout } from "../lib/testUtils";
|
||||
import { getEmailsReceivedByUser } from "../lib/testUtils";
|
||||
import { gotoPathAndExpectRedirectToOrgDomain } from "./lib/gotoPathAndExpectRedirectToOrgDomain";
|
||||
|
||||
async function expectEmailWithSubject(
|
||||
page: Page,
|
||||
@@ -103,7 +102,7 @@ function capitalize(text: string) {
|
||||
}
|
||||
|
||||
test.describe("Organization", () => {
|
||||
test("Admin should be able to create an org where an existing user is made an owner", async ({
|
||||
test("Admin should be able to do onboarding handover an org where an existing user is made an owner", async ({
|
||||
page,
|
||||
users,
|
||||
emails,
|
||||
@@ -141,113 +140,13 @@ test.describe("Organization", () => {
|
||||
await fillAndSubmitFirstStepAsAdmin(page, orgOwnerEmail, orgName, orgSlug);
|
||||
});
|
||||
|
||||
await expectOrganizationCreationEmailToBeSentWithLinks({
|
||||
page,
|
||||
emails,
|
||||
userEmail: orgOwnerEmail,
|
||||
oldUsername: orgOwnerUsernameOutsideOrg || "",
|
||||
newUsername: orgOwnerUsernameInOrg,
|
||||
orgSlug,
|
||||
});
|
||||
|
||||
await test.step("About the organization", async () => {
|
||||
// Choosing an avatar
|
||||
await page.getByTestId("open-upload-avatar-dialog").click();
|
||||
const fileChooserPromise = page.waitForEvent("filechooser");
|
||||
await page.getByText("Choose a file...").click();
|
||||
const fileChooser = await fileChooserPromise;
|
||||
await fileChooser.setFiles(path.join(__dirname, "../../public/apple-touch-icon.png"));
|
||||
await page.getByTestId("upload-avatar").click();
|
||||
|
||||
// About text
|
||||
await page.locator('textarea[name="about"]').fill("This is a testing org");
|
||||
await page.locator("button[type=submit]").click();
|
||||
|
||||
// Waiting to be in next step URL
|
||||
await page.waitForURL("/settings/organizations/*/onboard-members");
|
||||
});
|
||||
|
||||
await test.step("On-board administrators", async () => {
|
||||
await page.waitForSelector('[data-testid="pending-member-list"]');
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
|
||||
const adminEmail = users.trackEmail({ username: "rick", domain: `example.com` });
|
||||
|
||||
//can add members
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('[placeholder="email\\@example\\.com"]').fill(adminEmail);
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
await expect(page.getByTestId("pending-member-item").filter({ hasText: adminEmail })).toBeVisible();
|
||||
// TODO: Check if invited admin received the invitation email
|
||||
// await expectInvitationEmailToBeReceived(
|
||||
// page,
|
||||
// emails,
|
||||
// adminEmail,
|
||||
// `${orgName}'s admin invited you to join the organization ${orgName} on Cal.com`
|
||||
// );
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
|
||||
// can remove members
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(2);
|
||||
const lastRemoveMemberButton = page.getByTestId("remove-member-button").last();
|
||||
await lastRemoveMemberButton.click();
|
||||
await expect(page.getByTestId("pending-member-item")).toHaveCount(1);
|
||||
await page.getByTestId("publish-button").click();
|
||||
// Waiting to be in next step URL
|
||||
await page.waitForURL("/settings/organizations/*/add-teams");
|
||||
});
|
||||
|
||||
await test.step("Create teams", async () => {
|
||||
// Filling one team
|
||||
await page.locator('input[name="teams.0.name"]').fill("Marketing");
|
||||
|
||||
// Adding another team
|
||||
await page.getByTestId("add_a_team").click();
|
||||
await page.locator('input[name="teams.1.name"]').fill("Sales");
|
||||
|
||||
// Finishing the creation wizard
|
||||
await page.getByTestId("continue_or_checkout").click();
|
||||
await page.waitForURL("/event-types");
|
||||
});
|
||||
|
||||
await test.step("Login as org owner and pay", async () => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip(!IS_TEAM_BILLING_ENABLED, "Skipping paying for org as stripe is disabled");
|
||||
|
||||
await orgOwnerUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
const upgradeButton = await page.getByTestId("upgrade_org_banner_button");
|
||||
|
||||
await expect(upgradeButton).toBeVisible();
|
||||
await upgradeButton.click();
|
||||
// Check that stripe checkout is present
|
||||
const expectedUrl = "https://checkout.stripe.com";
|
||||
|
||||
await page.waitForURL((url) => url.href.startsWith(expectedUrl));
|
||||
const url = page.url();
|
||||
|
||||
// Check that the URL matches the expected URL
|
||||
expect(url).toContain(expectedUrl);
|
||||
|
||||
await fillStripeTestCheckout(page);
|
||||
|
||||
const upgradeButtonHidden = await page.getByTestId("upgrade_org_banner_button");
|
||||
|
||||
await expect(upgradeButtonHidden).toBeHidden();
|
||||
});
|
||||
|
||||
// Verify that the owner's old username redirect is properly set
|
||||
await gotoPathAndExpectRedirectToOrgDomain({
|
||||
page,
|
||||
org: {
|
||||
slug: orgSlug,
|
||||
},
|
||||
path: `/${orgOwnerUsernameOutsideOrg}`,
|
||||
expectedPath: `/${orgOwnerUsernameInOrg}`,
|
||||
await test.step("Handover", async () => {
|
||||
const onboardingUrl = await page.getByTestId("onboarding-url").textContent();
|
||||
expect(onboardingUrl).toContain("settings/organizations/new");
|
||||
});
|
||||
});
|
||||
|
||||
test("Admin should be able to create an org where the owner doesn't exist yet", async ({
|
||||
test.skip("Admin should be able to create an org where the owner doesn't exist yet", async ({
|
||||
page,
|
||||
users,
|
||||
emails,
|
||||
@@ -570,7 +469,7 @@ async function fillAndSubmitFirstStepAsAdmin(
|
||||
await page.locator("input[name=pricePerSeat]").fill("30");
|
||||
|
||||
await Promise.all([
|
||||
page.waitForResponse("**/api/trpc/organizations/create**"),
|
||||
page.waitForResponse("**/api/trpc/organizations/intentToCreateOrg**"),
|
||||
page.locator("button[type=submit]").click(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -646,6 +646,158 @@ test.describe("Out of office", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Date range filters", () => {
|
||||
test("Default date range filter set to `Last 7 Days`", async ({ page, users }) => {
|
||||
const user = await users.create({ name: `userOne=${Date.now()}` });
|
||||
await user.apiLogin();
|
||||
await page.goto("/settings/my-account/out-of-office");
|
||||
await page.waitForLoadState("domcontentloaded");
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="add-filter-item-dateRange"]').click();
|
||||
await expect(
|
||||
page
|
||||
.locator('[data-testid="filter-popover-trigger-dateRange"] span', { hasText: "Last 7 Days" })
|
||||
.nth(0)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("Can choose date range presets", async ({ page, users }) => {
|
||||
const user = await users.create({ name: `userOne=${Date.now()}` });
|
||||
await user.apiLogin();
|
||||
await page.goto("/settings/my-account/out-of-office");
|
||||
await page.waitForLoadState("domcontentloaded");
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="add-filter-item-dateRange"]').click();
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="filter-popover-trigger-dateRange"]').click();
|
||||
|
||||
await expect(page.locator('[data-testid="date-range-options-tdy"]')).toBeVisible(); //Today
|
||||
await expect(page.locator('[data-testid="date-range-options-w"]')).toBeVisible(); //Last 7 Days
|
||||
await expect(page.locator('[data-testid="date-range-options-t"]')).toBeVisible(); //Last 30 Days
|
||||
await expect(page.locator('[data-testid="date-range-options-m"]')).toBeVisible(); //Month to Date
|
||||
await expect(page.locator('[data-testid="date-range-options-y"]')).toBeVisible(); //Year to Date
|
||||
await expect(page.locator('[data-testid="date-range-options-c"]')).toBeVisible(); //Custom
|
||||
});
|
||||
|
||||
test("OOO records are fetched correctly w.r.t their end dates matching the date range filter selected.", async ({
|
||||
page,
|
||||
users,
|
||||
}) => {
|
||||
const member1Name = `member-1-${Date.now()}`;
|
||||
const member2Name = `member-2-${Date.now()}`;
|
||||
const member3Name = `member-3-${Date.now()}`;
|
||||
const teamMatesObj = [{ name: member1Name }, { name: member2Name }];
|
||||
const member3User = await users.create(
|
||||
{ name: member3Name },
|
||||
{
|
||||
hasTeam: true,
|
||||
teamRole: MembershipRole.MEMBER,
|
||||
teammates: teamMatesObj,
|
||||
}
|
||||
);
|
||||
const member1User = users.get().find((user) => user.name === member1Name);
|
||||
const member2User = users.get().find((user) => user.name === member2Name);
|
||||
|
||||
//create OOO for member3, start:currentDate+2Days, end:currentDate+4days (future ooo)
|
||||
await prisma.outOfOfficeEntry.create({
|
||||
data: {
|
||||
start: dayjs().startOf("day").add(2, "days").toDate(),
|
||||
end: dayjs().startOf("day").add(4, "days").toDate(),
|
||||
uuid: uuidv4(),
|
||||
user: { connect: { id: member3User?.id } },
|
||||
createdAt: new Date(),
|
||||
reason: {
|
||||
connect: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//create OOO for member3, start:currentDate-12Days, end:currentDate-10days (for Last 30 Days)
|
||||
await prisma.outOfOfficeEntry.create({
|
||||
data: {
|
||||
start: dayjs().startOf("day").subtract(12, "days").toDate(),
|
||||
end: dayjs().startOf("day").subtract(10, "days").toDate(),
|
||||
uuid: uuidv4(),
|
||||
user: { connect: { id: member3User?.id } },
|
||||
toUser: { connect: { id: member1User?.id } },
|
||||
createdAt: new Date(),
|
||||
reason: {
|
||||
connect: {
|
||||
id: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//create OOO for member3, start:currentDate-2Days, end:currentDate-4days (for Last 7 Days)
|
||||
await prisma.outOfOfficeEntry.create({
|
||||
data: {
|
||||
start: dayjs().startOf("day").subtract(4, "days").toDate(),
|
||||
end: dayjs().startOf("day").subtract(2, "days").toDate(),
|
||||
uuid: uuidv4(),
|
||||
user: { connect: { id: member3User?.id } },
|
||||
toUser: { connect: { id: member2User?.id } },
|
||||
createdAt: new Date(),
|
||||
reason: {
|
||||
connect: {
|
||||
id: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await member3User?.apiLogin();
|
||||
const entriesListRespPromise = page.waitForResponse(
|
||||
(response) => response.url().includes("outOfOfficeEntriesList") && response.status() === 200
|
||||
);
|
||||
await page.goto("/settings/my-account/out-of-office");
|
||||
await page.waitForLoadState("domcontentloaded");
|
||||
await entriesListRespPromise;
|
||||
|
||||
//By Default future OOO will be displayed
|
||||
//1 OOO record should be visible for member3, end=currentDate+4days
|
||||
expect(await page.locator('[data-testid^="table-redirect-"]').count()).toBe(1);
|
||||
await expect(page.locator(`data-testid=table-redirect-n-a`).nth(0)).toBeVisible();
|
||||
|
||||
//Default filter 'Last 7 Days' when DateRange Filter is selected
|
||||
await test.step("Default filter - 'Last 7 Days'", async () => {
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
await page.locator('[data-testid="add-filter-item-dateRange"]').click();
|
||||
await page.waitForResponse(
|
||||
(response) => response.url().includes("outOfOfficeEntriesList") && response.status() === 200
|
||||
);
|
||||
await page.locator('[data-testid="add-filter-button"]').click();
|
||||
|
||||
//1 OOO record should be visible for member3, end=currentDate-4days
|
||||
expect(await page.locator('[data-testid^="table-redirect-"]').count()).toBe(1);
|
||||
await expect(
|
||||
page.locator(`data-testid=table-redirect-${member2User?.username}`).nth(0)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
//Select 'Last 30 Days'
|
||||
await test.step("select 'Last 30 Days'", async () => {
|
||||
await page.locator('[data-testid="filter-popover-trigger-dateRange"]').click();
|
||||
await page.locator(`[data-testid="date-range-options-t"]`).click();
|
||||
await page.waitForResponse(
|
||||
(response) => response.url().includes("outOfOfficeEntriesList") && response.status() === 200
|
||||
);
|
||||
await page.locator('[data-testid="filter-popover-trigger-dateRange"]').click();
|
||||
|
||||
//2 OOO records should be visible end=currentDate-4days, end=currentDate-12days
|
||||
expect(await page.locator('[data-testid^="table-redirect-"]').count()).toBe(2);
|
||||
await expect(
|
||||
page.locator(`data-testid=table-redirect-${member2User?.username}`).nth(0)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(`data-testid=table-redirect-${member1User?.username}`).nth(0)
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function saveAndWaitForResponse(page: Page, expectedStatusCode = 200) {
|
||||
@@ -671,11 +823,11 @@ async function selectDateAndCreateOOO(
|
||||
redirectToUserId?: number,
|
||||
expectedStatusCode = 200,
|
||||
forTeamMember = false,
|
||||
month: "previous-month" | "next-month" = "next-month",
|
||||
month: "previous" | "next" = "next",
|
||||
editMode = false
|
||||
) {
|
||||
const t = await localize("en");
|
||||
await page.locator(`button[name="${month}"]`).click();
|
||||
await page.locator(`button[name="${month}-month"]`).click();
|
||||
await page.locator(`button[name="day"]:text-is("${fromDate}")`).nth(0).click();
|
||||
await page.locator(`button[name="day"]:text-is("${toDate}")`).nth(0).click();
|
||||
editMode
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "تم التعطيل",
|
||||
"disable": "تعطيل",
|
||||
"billing": "الفوترة",
|
||||
"here": "هنا",
|
||||
"manage_your_billing_info": "قم بإدارة معلومات الفوترة لديك وإلغاء اشتراكك.",
|
||||
"availability": "الأوقات المتاحة",
|
||||
"edit_availability": "تعديل الإتاحة",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "التفريغ النصي من مكالمة الأخيرة على {{appName}} جاهز للتحميل. الروابط متاحة لمدة ساعة واحدة فقط",
|
||||
"you_can_download_transcript_from_attachments": "يمكنك أيضاً تحميل النص المكتوب من المرفقات",
|
||||
"link_valid_for_12_hrs": "ملاحظة: رابط التحميل متاح لمدة 12 ساعة فقط. يمكنك إنشاء رابط تحميل جديد بإتباع التعليمات <1>هنا</1>.",
|
||||
"link_valid_for_12_hrs_description": "ملاحظة: رابط التنزيل صالح لمدة 12 ساعة فقط. يمكنك إنشاء رابط تنزيل جديد باتباع التعليمات.",
|
||||
"create_your_first_form": "إنشاء أول استمارة",
|
||||
"create_your_first_form_description": "باستخدام نماذج المسارات، يمكنك طرح أسئلة التأهيل والتوجيه إلى الشخص/نوع الحدث المناسب.",
|
||||
"create_your_first_webhook": "إنشاء أول Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "أنت تقوم بحجز تجريبي.",
|
||||
"icon_showcase": "معرض الأيقونات",
|
||||
"icons_showcase": "معرض الأيقونات",
|
||||
"migrating_from_team": "الانتقال من الفريق",
|
||||
"feature_currently_disabled": "الميزة معطلة حالياً",
|
||||
"choose_an_option": "اختر خيارًا",
|
||||
"enter_option_value": "أدخل قيمة الخيار",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "تصاعدي",
|
||||
"desc": "تنازلي",
|
||||
"verify_email_change": "تأكيد تغيير البريد الإلكتروني",
|
||||
"organization_slug_taken": "الاسم المختصر للمؤسسة مستخدم بالفعل",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "لا يمكنك إنشاء مؤسسة لأنك بالفعل جزء من مؤسسة",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "تحتاج إلى إكمال عملية تأهيل المستخدم قبل إنشاء مؤسسة",
|
||||
"use_company_email_to_create_an_organization": "استخدم البريد الإلكتروني للشركة لإنشاء مؤسسة",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "لا يمكنك إنشاء مؤسسة على المنصة لأنك بالفعل جزء من فريق",
|
||||
"you_need_to_have_minimum_published_teams": "تحتاج إلى الحد الأدنى من الفرق المنشورة",
|
||||
"you_are_part_of_this_organization_already": "أنت بالفعل جزء من هذه المؤسسة",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "أنت جزء من مؤسسة أخرى، لا يمكنك إنشاء مؤسسة جديدة",
|
||||
"organization_payment_success": "نجاح دفع المؤسسة",
|
||||
"organization_payment_success_description": "تم إنشاء مؤسستك بنجاح",
|
||||
"this_may_take_a_few_seconds": "قد يستغرق هذا بضع ثوانٍ...",
|
||||
"organization_onboarding_status": "حالة تأهيل المؤسسة",
|
||||
"organization_onboarding_status_description": "وصف حالة تأهيل المؤسسة",
|
||||
"payment_failed": "فشل الدفع",
|
||||
"payment_failed_description": "لقد فشلت عملية الدفع الخاصة بك. يرجى المحاولة مرة أخرى.",
|
||||
"creating_your_organization": "جارٍ إنشاء مؤسستك",
|
||||
"organization_onboarding_already_completed": "تم إكمال تأهيل المؤسسة بالفعل",
|
||||
"organization_onboarding_already_exists": "تأهيل المؤسسة موجود بالفعل",
|
||||
"organization_onboarding_not_found": "لم يتم العثور على تأهيل المؤسسة",
|
||||
"payment_successful": "تم الدفع بنجاح",
|
||||
"handover_onboarding_page_title": "تسليم عملية التأهيل",
|
||||
"handover_onboarding_page_description": "تسليم عملية التأهيل للمستخدم",
|
||||
"organization_already_exists_with_this_slug": "المؤسسة موجودة بالفعل بهذا الاسم المختصر",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "ليس لديك الصلاحية لإنشاء مؤسسة لهذا البريد الإلكتروني",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "ليس لديك الصلاحية لنقل فريق واحد أو أكثر",
|
||||
"organization_has_subscription_already": "المؤسسة لديها اشتراك بالفعل",
|
||||
"rr_reset_interval": "فترة إعادة تعيين الترتيب الدوري",
|
||||
"interval": "الفترة",
|
||||
"rr_reset_interval_description": "تحدد مدى تكرار إعادة تعيين عدد الحجوزات في الترتيب الدوري لضمان توزيع متوازن.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Deaktiv",
|
||||
"disable": "Deaktiv et",
|
||||
"billing": "Ödəniş",
|
||||
"here": "burada",
|
||||
"manage_your_billing_info": "Ödəniş məlumatlarınızı idarə edin və abunəliyinizi ləğv edin.",
|
||||
"availability": "Mövcudluq",
|
||||
"edit_availability": "Mövcudluğu redaktə et",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "{{appName}} üzərindən son zənginizin transkripti yükləməyə hazırdır. Link yalnız 1 saat etibarlıdır",
|
||||
"you_can_download_transcript_from_attachments": "Siz həmçinin transkripti əlavələrdən yükləyə bilərsiniz",
|
||||
"link_valid_for_12_hrs": "Qeyd: Yükləmə linki yalnız 12 saat etibarlıdır. Yeni yükləmə linki yaratmaq üçün təlimatları izləyərək <1>buradan</1> əldə edə bilərsiniz.",
|
||||
"link_valid_for_12_hrs_description": "Qeyd: Yükləmə linki yalnız 12 saat ərzində etibarlıdır. Təlimatlara əməl edərək yeni yükləmə linki yarada bilərsiniz.",
|
||||
"create_your_first_form": "İlk formanızı yaradın",
|
||||
"create_your_first_form_description": "Yönləndirmə formaları ilə uyğun suallar verə və doğru şəxsə və ya tədbir növünə yönləndirə bilərsiniz.",
|
||||
"create_your_first_webhook": "İlk Webhook-unuzu yaradın",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Siz test rezervasiyası edirsiniz.",
|
||||
"icon_showcase": "İkon nümayişi",
|
||||
"icons_showcase": "İkonların nümayişi",
|
||||
"migrating_from_team": "Komandadan köçürülür",
|
||||
"feature_currently_disabled": "Funksiya hazırda deaktivdir",
|
||||
"choose_an_option": "Seçim edin",
|
||||
"enter_option_value": "Seçim dəyərini daxil edin",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Artan",
|
||||
"desc": "Azalan",
|
||||
"verify_email_change": "E-poçt dəyişikliyini təsdiqlə",
|
||||
"organization_slug_taken": "Təşkilat slaqı artıq istifadə olunub",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Siz artıq bir təşkilatın üzvü olduğunuz üçün yeni təşkilat yarada bilməzsiniz",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Təşkilat yaratmadan əvvəl istifadəçi qeydiyyatını tamamlamalısınız",
|
||||
"use_company_email_to_create_an_organization": "Təşkilat yaratmaq üçün şirkət e-poçtundan istifadə edin",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Siz artıq bir komandanın üzvü olduğunuz üçün platforma təşkilatı yarada bilməzsiniz",
|
||||
"you_need_to_have_minimum_published_teams": "Minimum sayda dərc edilmiş komandalarınız olmalıdır",
|
||||
"you_are_part_of_this_organization_already": "Siz artıq bu təşkilatın üzvüsünüz",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Siz başqa bir təşkilatın üzvüsünüz, yeni təşkilat yarada bilməzsiniz",
|
||||
"organization_payment_success": "Təşkilat ödənişi uğurludur",
|
||||
"organization_payment_success_description": "Təşkilatınız uğurla yaradılıb",
|
||||
"this_may_take_a_few_seconds": "Bu bir neçə saniyə çəkə bilər...",
|
||||
"organization_onboarding_status": "Təşkilat qeydiyyat statusu",
|
||||
"organization_onboarding_status_description": "Təşkilat qeydiyyat statusunun təsviri",
|
||||
"payment_failed": "Ödəniş uğursuz oldu",
|
||||
"payment_failed_description": "Ödənişiniz uğursuz oldu. Zəhmət olmasa yenidən cəhd edin.",
|
||||
"creating_your_organization": "Təşkilatınız yaradılır",
|
||||
"organization_onboarding_already_completed": "Təşkilat qeydiyyatı artıq tamamlanıb",
|
||||
"organization_onboarding_already_exists": "Təşkilat qeydiyyatı artıq mövcuddur",
|
||||
"organization_onboarding_not_found": "Təşkilat qeydiyyatı tapılmadı",
|
||||
"payment_successful": "Ödəniş uğurlu oldu",
|
||||
"handover_onboarding_page_title": "Qeydiyyatın təhvil verilməsi",
|
||||
"handover_onboarding_page_description": "İstifadəçiyə qeydiyyatın təhvil verilməsi",
|
||||
"organization_already_exists_with_this_slug": "Bu slug ilə təşkilat artıq mövcuddur",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Bu e-poçt üçün təşkilat yaratmağa icazəniz yoxdur",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Bir və ya bir neçə komandanı köçürməyə icazəniz yoxdur",
|
||||
"organization_has_subscription_already": "Təşkilatın artıq abunəliyi var",
|
||||
"rr_reset_interval": "Round Robin Sıfırlama İntervalı",
|
||||
"interval": "İnterval",
|
||||
"rr_reset_interval_description": "Tarazlı paylaşımı təmin etmək üçün round robin rezervasiya sayının nə qədər tez-tez sıfırlanacağını müəyyən edir.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Деактивирано",
|
||||
"disable": "Деактивиране",
|
||||
"billing": "Фактуриране",
|
||||
"here": "тук",
|
||||
"manage_your_billing_info": "Управлявайте вашата информация за фактуриране и прекратете абонамента си.",
|
||||
"availability": "Наличност",
|
||||
"edit_availability": "Редактиране на наличност",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Транскриптът от последния ви разговор в {{appName}} е готов за изтегляне. Линковете са валидни само за 1 час",
|
||||
"you_can_download_transcript_from_attachments": "Можете също да изтеглите транскрипта от прикачените файлове",
|
||||
"link_valid_for_12_hrs": "Забележка: Линкът за изтегляне е валиден само за 12 часа. Можете да генерирате нов линк за изтегляне, като следвате инструкциите <1>тук</1>.",
|
||||
"link_valid_for_12_hrs_description": "Забележка: Връзката за изтегляне е валидна само за 12 часа. Можете да генерирате нова връзка за изтегляне, като следвате инструкциите.",
|
||||
"create_your_first_form": "Създайте първия си формуляр",
|
||||
"create_your_first_form_description": "С формулярите за маршрутизиране можете да задавате квалификационни въпроси и да пренасочвате към правилния човек или тип събитие.",
|
||||
"create_your_first_webhook": "Създайте първия си уебхук",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Правите тестова резервация.",
|
||||
"icon_showcase": "Галерия с икони",
|
||||
"icons_showcase": "Галерия с икони",
|
||||
"migrating_from_team": "Мигриране от екип",
|
||||
"feature_currently_disabled": "Функцията е деактивирана в момента",
|
||||
"choose_an_option": "Изберете опция",
|
||||
"enter_option_value": "Въведете стойност на опцията",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Възх",
|
||||
"desc": "Низх",
|
||||
"verify_email_change": "Потвърди промяната на имейл",
|
||||
"organization_slug_taken": "Слъгът на организацията вече е зает",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Не можете да създадете организация, тъй като вече сте част от организация",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Трябва да завършите въвеждането на потребителя, преди да създадете организация",
|
||||
"use_company_email_to_create_an_organization": "Използвайте фирмен имейл, за да създадете организация",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Не можете да създадете платформена организация, тъй като вече сте част от екип",
|
||||
"you_need_to_have_minimum_published_teams": "Трябва да имате минимален брой публикувани екипи",
|
||||
"you_are_part_of_this_organization_already": "Вече сте част от тази организация",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Вие сте част от друга организация, не можете да създадете нова организация",
|
||||
"organization_payment_success": "Успешно плащане за организацията",
|
||||
"organization_payment_success_description": "Вашата организация е създадена успешно",
|
||||
"this_may_take_a_few_seconds": "Това може да отнеме няколко секунди...",
|
||||
"organization_onboarding_status": "Статус на въвеждане в организацията",
|
||||
"organization_onboarding_status_description": "Описание на статуса на въвеждане в организацията",
|
||||
"payment_failed": "Плащането не бе успешно",
|
||||
"payment_failed_description": "Вашето плащане не бе успешно. Моля, опитайте отново.",
|
||||
"creating_your_organization": "Създаване на вашата организация",
|
||||
"organization_onboarding_already_completed": "Въвеждането в организацията вече е завършено",
|
||||
"organization_onboarding_already_exists": "Въвеждането в организацията вече съществува",
|
||||
"organization_onboarding_not_found": "Въвеждането в организацията не е намерено",
|
||||
"payment_successful": "Успешно плащане",
|
||||
"handover_onboarding_page_title": "Предаване на въвеждането",
|
||||
"handover_onboarding_page_description": "Предаване на въвеждането на потребителя",
|
||||
"organization_already_exists_with_this_slug": "Вече съществува организация с този слъг",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Нямате разрешение да създадете организация за този имейл",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Нямате разрешение да мигрирате един или повече от екипите",
|
||||
"organization_has_subscription_already": "Организацията вече има абонамент",
|
||||
"rr_reset_interval": "Интервал за нулиране на Round Robin",
|
||||
"interval": "Интервал",
|
||||
"rr_reset_interval_description": "Определя колко често се нулира броят на резервациите в round robin, за да се осигури балансирано разпределение.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Desactivat",
|
||||
"disable": "Desactivar",
|
||||
"billing": "Facturació",
|
||||
"here": "aquí",
|
||||
"manage_your_billing_info": "Gestiona la teva informació de facturació i cancel·la la teva subscripció.",
|
||||
"availability": "Disponibilitat",
|
||||
"edit_availability": "Editar disponibilitat",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "La transcripció de la teva trucada recent a {{appName}} està llesta per descarregar. Els enllaços només són vàlids durant 1 hora",
|
||||
"you_can_download_transcript_from_attachments": "També podeu descarregar la transcripció des dels arxius adjunts",
|
||||
"link_valid_for_12_hrs": "Nota: L'enllaç de descàrrega només és vàlid durant 12 hores. Pots generar un nou enllaç seguint les instruccions <1>aquí</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: L'enllaç de descàrrega només és vàlid durant 12 hores. Podeu generar un nou enllaç de descàrrega seguint les instruccions.",
|
||||
"create_your_first_form": "Crea el teu primer formulari",
|
||||
"create_your_first_form_description": "Amb els Formularis de Ruta pots fer preguntes de qualificació i redirigir a la persona o tipus d'esdeveniment correcte.",
|
||||
"create_your_first_webhook": "Crea el teu primer Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Estàs fent una reserva de prova.",
|
||||
"icon_showcase": "Mostra d'icones",
|
||||
"icons_showcase": "Mostra d'icones",
|
||||
"migrating_from_team": "Migrant des de l'equip",
|
||||
"feature_currently_disabled": "La funcionalitat està actualment desactivada",
|
||||
"choose_an_option": "Tria una opció",
|
||||
"enter_option_value": "Introdueix el valor de l'opció",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email_change": "Verifica el canvi de correu electrònic",
|
||||
"organization_slug_taken": "L'slug de l'organització ja està en ús",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "No podeu crear una organització perquè ja formeu part d'una",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Heu de completar la incorporació d'usuari abans de crear una organització",
|
||||
"use_company_email_to_create_an_organization": "Utilitzeu el correu electrònic de l'empresa per crear una organització",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "No podeu crear una organització de plataforma perquè ja formeu part d'un equip",
|
||||
"you_need_to_have_minimum_published_teams": "Necessiteu tenir un mínim d'equips publicats",
|
||||
"you_are_part_of_this_organization_already": "Ja formeu part d'aquesta organització",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Formeu part d'una altra organització, no podeu crear-ne una de nova",
|
||||
"organization_payment_success": "Pagament de l'organització realitzat amb èxit",
|
||||
"organization_payment_success_description": "La vostra organització s'ha creat correctament",
|
||||
"this_may_take_a_few_seconds": "Això pot trigar uns segons...",
|
||||
"organization_onboarding_status": "Estat d'incorporació de l'organització",
|
||||
"organization_onboarding_status_description": "Descripció de l'estat d'incorporació de l'organització",
|
||||
"payment_failed": "El pagament ha fallat",
|
||||
"payment_failed_description": "El vostre pagament ha fallat. Si us plau, torneu-ho a provar.",
|
||||
"creating_your_organization": "Creant la vostra organització",
|
||||
"organization_onboarding_already_completed": "La incorporació de l'organització ja s'ha completat",
|
||||
"organization_onboarding_already_exists": "La incorporació de l'organització ja existeix",
|
||||
"organization_onboarding_not_found": "No s'ha trobat la incorporació de l'organització",
|
||||
"payment_successful": "Pagament realitzat amb èxit",
|
||||
"handover_onboarding_page_title": "Traspàs d'incorporació",
|
||||
"handover_onboarding_page_description": "Traspàs d'incorporació a l'usuari",
|
||||
"organization_already_exists_with_this_slug": "Ja existeix una organització amb aquest slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "No teniu permís per crear una organització per a aquest correu electrònic",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "No teniu permís per migrar un o més dels equips",
|
||||
"organization_has_subscription_already": "L'organització ja té una subscripció",
|
||||
"rr_reset_interval": "Interval de reinici del Round Robin",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Determina amb quina freqüència es reinicia el comptador de reserves del round robin per assegurar una distribució equilibrada.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Vypnuto",
|
||||
"disable": "Vypnout",
|
||||
"billing": "Fakturace",
|
||||
"here": "zde",
|
||||
"manage_your_billing_info": "Spravujte své fakturační údaje a zrušte své předplatné.",
|
||||
"availability": "Dostupnost",
|
||||
"edit_availability": "Upravit dostupnost",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Přepis z vašeho nedávného hovoru na {{appName}} je připraven ke stažení. Odkazy jsou platné pouze 1 hodinu",
|
||||
"you_can_download_transcript_from_attachments": "Přepis si můžete také stáhnout z příloh",
|
||||
"link_valid_for_12_hrs": "Poznámka: Odkaz ke stažení je platný pouze 12 hodin. Nový odkaz ke stažení můžete vygenerovat podle pokynů <1>zde</1>.",
|
||||
"link_valid_for_12_hrs_description": "Poznámka: Odkaz ke stažení je platný pouze 12 hodin. Nový odkaz ke stažení můžete vygenerovat podle pokynů.",
|
||||
"create_your_first_form": "Vytvořte svůj první formulář",
|
||||
"create_your_first_form_description": "Pomocí adresných formulářů můžete klást kvalifikační otázky a adresovat je správné osobě nebo typu události.",
|
||||
"create_your_first_webhook": "Vytvořte svůj první webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Provádíte testovací rezervaci.",
|
||||
"icon_showcase": "Ukázka ikon",
|
||||
"icons_showcase": "Ukázka ikon",
|
||||
"migrating_from_team": "Migrace z týmu",
|
||||
"feature_currently_disabled": "Funkce je momentálně vypnutá",
|
||||
"choose_an_option": "Vyberte možnost",
|
||||
"enter_option_value": "Zadejte hodnotu možnosti",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Vzestupně",
|
||||
"desc": "Sestupně",
|
||||
"verify_email_change": "Ověřit změnu e-mailu",
|
||||
"organization_slug_taken": "Slug organizace je již obsazen",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Nemůžete vytvořit organizaci, protože již jste součástí jiné organizace",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Před vytvořením organizace musíte dokončit úvodní zaškolení uživatele",
|
||||
"use_company_email_to_create_an_organization": "Pro vytvoření organizace použijte firemní e-mail",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Nemůžete vytvořit platformní organizaci, protože již jste součástí týmu",
|
||||
"you_need_to_have_minimum_published_teams": "Musíte mít minimální počet publikovaných týmů",
|
||||
"you_are_part_of_this_organization_already": "Již jste součástí této organizace",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Jste součástí jiné organizace, nelze vytvořit novou organizaci",
|
||||
"organization_payment_success": "Platba za organizaci byla úspěšná",
|
||||
"organization_payment_success_description": "Vaše organizace byla úspěšně vytvořena",
|
||||
"this_may_take_a_few_seconds": "Toto může trvat několik sekund...",
|
||||
"organization_onboarding_status": "Stav úvodního zaškolení organizace",
|
||||
"organization_onboarding_status_description": "Popis stavu úvodního zaškolení organizace",
|
||||
"payment_failed": "Platba se nezdařila",
|
||||
"payment_failed_description": "Vaše platba se nezdařila. Zkuste to prosím znovu.",
|
||||
"creating_your_organization": "Vytváření vaší organizace",
|
||||
"organization_onboarding_already_completed": "Úvodní zaškolení organizace již bylo dokončeno",
|
||||
"organization_onboarding_already_exists": "Úvodní zaškolení organizace již existuje",
|
||||
"organization_onboarding_not_found": "Úvodní zaškolení organizace nebylo nalezeno",
|
||||
"payment_successful": "Platba byla úspěšná",
|
||||
"handover_onboarding_page_title": "Předání úvodního zaškolení",
|
||||
"handover_onboarding_page_description": "Předání úvodního zaškolení uživateli",
|
||||
"organization_already_exists_with_this_slug": "Organizace s tímto slugem již existuje",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nemáte oprávnění vytvořit organizaci pro tento e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nemáte oprávnění migrovat jeden nebo více týmů",
|
||||
"organization_has_subscription_already": "Organizace již má předplatné",
|
||||
"rr_reset_interval": "Interval resetování Round Robin",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Určuje, jak často se resetuje počet rezervací v systému round robin pro zajištění vyváženého rozdělení.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Deaktiveret",
|
||||
"disable": "Deaktivér",
|
||||
"billing": "Fakturering",
|
||||
"here": "her",
|
||||
"manage_your_billing_info": "Administrer dine faktureringsoplysninger og annuller dit abonnement.",
|
||||
"availability": "Tilgængelighed",
|
||||
"edit_availability": "Redigér tilgængelighed",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Udskrift fra dit seneste opkald på {{appName}} er klar til download. Links er kun gyldige i 1 time",
|
||||
"you_can_download_transcript_from_attachments": "Du kan også downloade udskriften fra vedhæftede filer",
|
||||
"link_valid_for_12_hrs": "Bemærk: Downloadlinket er kun gyldigt i 12 timer. Du kan generere et nyt downloadlink ved at følge instruktionerne <1>her</1>.",
|
||||
"link_valid_for_12_hrs_description": "Bemærk: Downloadlinket er kun gyldigt i 12 timer. Du kan generere et nyt downloadlink ved at følge instruktionerne.",
|
||||
"create_your_first_form": "Opret din første formular",
|
||||
"create_your_first_form_description": "Med Routing Forms kan du stille kvalificerende spørgsmål og rute til den korrekte person eller begivenhedstype.",
|
||||
"create_your_first_webhook": "Opret din første Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Du foretager en testbooking.",
|
||||
"icon_showcase": "Ikonoversigt",
|
||||
"icons_showcase": "Ikonoversigt",
|
||||
"migrating_from_team": "Migrerer fra team",
|
||||
"feature_currently_disabled": "Funktionen er i øjeblikket deaktiveret",
|
||||
"choose_an_option": "Vælg en mulighed",
|
||||
"enter_option_value": "Indtast værdi for mulighed",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Stigende",
|
||||
"desc": "Faldende",
|
||||
"verify_email_change": "Bekræft ændring af e-mail",
|
||||
"organization_slug_taken": "Organisationens slug er allerede taget",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Du kan ikke oprette en organisation, da du allerede er en del af en organisation",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Du skal gennemføre brugeronboarding, før du opretter en organisation",
|
||||
"use_company_email_to_create_an_organization": "Brug firmamail til at oprette en organisation",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Du kan ikke oprette en platformsorganisation, da du allerede er en del af et team",
|
||||
"you_need_to_have_minimum_published_teams": "Du skal have et minimum af offentliggjorte teams",
|
||||
"you_are_part_of_this_organization_already": "Du er allerede en del af denne organisation",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Du er en del af en anden organisation, kan ikke oprette en ny organisation",
|
||||
"organization_payment_success": "Organisationsbetaling gennemført",
|
||||
"organization_payment_success_description": "Din organisation er blevet oprettet med succes",
|
||||
"this_may_take_a_few_seconds": "Dette kan tage et par sekunder...",
|
||||
"organization_onboarding_status": "Status for organisationens onboarding",
|
||||
"organization_onboarding_status_description": "Beskrivelse af status for organisationens onboarding",
|
||||
"payment_failed": "Betaling mislykkedes",
|
||||
"payment_failed_description": "Din betaling er mislykkedes. Prøv venligst igen.",
|
||||
"creating_your_organization": "Opretter din organisation",
|
||||
"organization_onboarding_already_completed": "Organisationens onboarding er allerede gennemført",
|
||||
"organization_onboarding_already_exists": "Organisationens onboarding eksisterer allerede",
|
||||
"organization_onboarding_not_found": "Organisationens onboarding blev ikke fundet",
|
||||
"payment_successful": "Betaling gennemført",
|
||||
"handover_onboarding_page_title": "Overdragelse af onboarding",
|
||||
"handover_onboarding_page_description": "Overdragelse af onboarding til brugeren",
|
||||
"organization_already_exists_with_this_slug": "En organisation med dette slug findes allerede",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Du har ikke tilladelse til at oprette en organisation for denne e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Du har ikke tilladelse til at migrere et eller flere af teamene",
|
||||
"organization_has_subscription_already": "Organisationen har allerede et abonnement",
|
||||
"rr_reset_interval": "Round Robin nulstillingsinterval",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Bestemmer hvor ofte round robin-bookingtællingen nulstilles for at sikre en balanceret fordeling.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Deaktiviert",
|
||||
"disable": "Deaktivieren",
|
||||
"billing": "Abrechnung",
|
||||
"here": "hier",
|
||||
"manage_your_billing_info": "Verwalten Sie Ihre Rechnungsinformationen und kündigen Sie Ihr Abonnement.",
|
||||
"availability": "Verfügbarkeit",
|
||||
"edit_availability": "Verfügbarkeit bearbeiten",
|
||||
@@ -1117,7 +1118,7 @@
|
||||
"duplicate": "Duplizieren",
|
||||
"offer_seats": "Plätze anbieten",
|
||||
"offer_seats_description": "Bieten Sie Plätze für Buchungen an (dies deaktiviert Gäste & Opt-in-Buchungen)",
|
||||
"seats_available_other": "Verfügbare Plätze",
|
||||
"seats_available_other": "Plätze verfügbar",
|
||||
"seats_nearly_full": "Plätze fast voll",
|
||||
"seats_half_full": "Plätze werden schnell belegt",
|
||||
"number_of_seats": "Anzahl der Plätze pro Termin",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transkript von Ihrem letzten Anruf bei {{appName}} ist zum Herunterladen bereit. Links sind nur für 1 Stunde gültig",
|
||||
"you_can_download_transcript_from_attachments": "Sie können das Protokoll auch aus den Anhängen herunterladen",
|
||||
"link_valid_for_12_hrs": "Hinweis: Der Download-Link ist nur für 12 Stunden gültig. Sie können einen neuen Downloadlink durch das Befolgen der Anweisungen <1>hier</1> generieren.",
|
||||
"link_valid_for_12_hrs_description": "Hinweis: Der Download-Link ist nur 12 Stunden gültig. Sie können einen neuen Download-Link generieren, indem Sie den Anweisungen folgen.",
|
||||
"create_your_first_form": "Erstellen Sie Ihr erstes Formular",
|
||||
"create_your_first_form_description": "Mithilfe von Leitungsformularen können Sie qualifizierende Fragen stellen und zur richtigen Person oder zum richtigen Veranstaltungstyp weiterleiten.",
|
||||
"create_your_first_webhook": "Erstellen Sie Ihren ersten Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Sie führen eine Testbuchung durch.",
|
||||
"icon_showcase": "Icon-Übersicht",
|
||||
"icons_showcase": "Icons-Übersicht",
|
||||
"migrating_from_team": "Migration vom Team",
|
||||
"feature_currently_disabled": "Funktion ist derzeit deaktiviert",
|
||||
"choose_an_option": "Option auswählen",
|
||||
"enter_option_value": "Optionswert eingeben",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Aufsteigend",
|
||||
"desc": "Absteigend",
|
||||
"verify_email_change": "E-Mail-Änderung bestätigen",
|
||||
"organization_slug_taken": "Der Organisations-Slug ist bereits vergeben",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Sie können keine Organisation erstellen, da Sie bereits Teil einer Organisation sind",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Sie müssen das Benutzer-Onboarding abschließen, bevor Sie eine Organisation erstellen können",
|
||||
"use_company_email_to_create_an_organization": "Verwenden Sie die Firmen-E-Mail-Adresse, um eine Organisation zu erstellen",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Sie können keine Plattform-Organisation erstellen, da Sie bereits Teil eines Teams sind",
|
||||
"you_need_to_have_minimum_published_teams": "Sie müssen mindestens veröffentlichte Teams haben",
|
||||
"you_are_part_of_this_organization_already": "Sie sind bereits Teil dieser Organisation",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Sie sind Teil einer anderen Organisation und können keine neue Organisation erstellen",
|
||||
"organization_payment_success": "Organisationszahlung erfolgreich",
|
||||
"organization_payment_success_description": "Ihre Organisation wurde erfolgreich erstellt",
|
||||
"this_may_take_a_few_seconds": "Dies kann einige Sekunden dauern...",
|
||||
"organization_onboarding_status": "Status des Organisations-Onboardings",
|
||||
"organization_onboarding_status_description": "Beschreibung des Organisations-Onboarding-Status",
|
||||
"payment_failed": "Zahlung fehlgeschlagen",
|
||||
"payment_failed_description": "Ihre Zahlung ist fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"creating_your_organization": "Ihre Organisation wird erstellt",
|
||||
"organization_onboarding_already_completed": "Organisations-Onboarding bereits abgeschlossen",
|
||||
"organization_onboarding_already_exists": "Organisations-Onboarding existiert bereits",
|
||||
"organization_onboarding_not_found": "Organisations-Onboarding nicht gefunden",
|
||||
"payment_successful": "Zahlung erfolgreich",
|
||||
"handover_onboarding_page_title": "Übergabe-Onboarding",
|
||||
"handover_onboarding_page_description": "Übergabe des Onboardings an den Benutzer",
|
||||
"organization_already_exists_with_this_slug": "Eine organisation mit diesem slug existiert bereits",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Sie haben keine berechtigung, eine organisation für diese e-mail-adresse zu erstellen",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Sie haben keine berechtigung, eines oder mehrere der teams zu migrieren",
|
||||
"organization_has_subscription_already": "Die organisation hat bereits ein abonnement",
|
||||
"rr_reset_interval": "Round Robin Zurücksetzungsintervall",
|
||||
"interval": "Intervall",
|
||||
"rr_reset_interval_description": "Legt fest, wie oft der Round Robin Buchungszähler zurückgesetzt wird, um eine ausgewogene Verteilung zu gewährleisten.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Απενεργοποιημένο",
|
||||
"disable": "Απενεργοποίηση",
|
||||
"billing": "Χρεώσεις",
|
||||
"here": "εδώ",
|
||||
"manage_your_billing_info": "Διαχειριστείτε τις πληροφορίες χρέωσης και ακυρώστε τη συνδρομή σας.",
|
||||
"availability": "Διαθεσιμότητα",
|
||||
"edit_availability": "Επεξεργασία διαθεσιμότητας",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Η απομαγνητοφώνηση από την πρόσφατη κλήση σας στο {{appName}} είναι έτοιμη για λήψη. Οι σύνδεσμοι ισχύουν μόνο για 1 ώρα",
|
||||
"you_can_download_transcript_from_attachments": "Μπορείτε επίσης να κατεβάσετε το αντίγραφο από τα συνημμένα",
|
||||
"link_valid_for_12_hrs": "Σημείωση: Ο σύνδεσμος λήψης ισχύει μόνο για 12 ώρες. Μπορείτε να δημιουργήσετε νέο σύνδεσμο λήψης ακολουθώντας τις οδηγίες <1>εδώ</1>.",
|
||||
"link_valid_for_12_hrs_description": "Σημείωση: Ο σύνδεσμος λήψης ισχύει μόνο για 12 ώρες. Μπορείτε να δημιουργήσετε νέο σύνδεσμο λήψης ακολουθώντας τις οδηγίες.",
|
||||
"create_your_first_form": "Δημιουργήστε την πρώτη σας φόρμα",
|
||||
"create_your_first_form_description": "Με τις φόρμες δρομολόγησης μπορείτε να θέσετε ερωτήσεις αξιολόγησης και να κατευθύνετε στο σωστό άτομο ή τύπο εκδήλωσης.",
|
||||
"create_your_first_webhook": "Δημιουργήστε το πρώτο σας Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Κάνετε μια δοκιμαστική κράτηση.",
|
||||
"icon_showcase": "Παρουσίαση εικονιδίων",
|
||||
"icons_showcase": "Παρουσίαση εικονιδίων",
|
||||
"migrating_from_team": "Μετάβαση από ομάδα",
|
||||
"feature_currently_disabled": "Η λειτουργία είναι απενεργοποιημένη",
|
||||
"choose_an_option": "Επιλέξτε μια επιλογή",
|
||||
"enter_option_value": "Εισαγάγετε την τιμή της επιλογής",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Αύξουσα",
|
||||
"desc": "Φθίνουσα",
|
||||
"verify_email_change": "Επαλήθευση αλλαγής email",
|
||||
"organization_slug_taken": "Το αναγνωριστικό του οργανισμού χρησιμοποιείται ήδη",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Δεν μπορείτε να δημιουργήσετε έναν οργανισμό καθώς είστε ήδη μέλος ενός οργανισμού",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Πρέπει να ολοκληρώσετε την εισαγωγή χρήστη πριν δημιουργήσετε έναν οργανισμό",
|
||||
"use_company_email_to_create_an_organization": "Χρησιμοποιήστε εταιρικό email για να δημιουργήσετε έναν οργανισμό",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Δεν μπορείτε να δημιουργήσετε έναν οργανισμό πλατφόρμας καθώς είστε ήδη μέλος μιας ομάδας",
|
||||
"you_need_to_have_minimum_published_teams": "Πρέπει να έχετε τον ελάχιστο αριθμό δημοσιευμένων ομάδων",
|
||||
"you_are_part_of_this_organization_already": "Είστε ήδη μέλος αυτού του οργανισμού",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Είστε μέλος άλλου οργανισμού, δεν μπορείτε να δημιουργήσετε νέο οργανισμό",
|
||||
"organization_payment_success": "Επιτυχής πληρωμή οργανισμού",
|
||||
"organization_payment_success_description": "Ο οργανισμός σας δημιουργήθηκε με επιτυχία",
|
||||
"this_may_take_a_few_seconds": "Αυτό μπορεί να διαρκέσει μερικά δευτερόλεπτα...",
|
||||
"organization_onboarding_status": "Κατάσταση εισαγωγής οργανισμού",
|
||||
"organization_onboarding_status_description": "Περιγραφή κατάστασης εισαγωγής οργανισμού",
|
||||
"payment_failed": "Η πληρωμή απέτυχε",
|
||||
"payment_failed_description": "Η πληρωμή σας απέτυχε. Παρακαλώ δοκιμάστε ξανά.",
|
||||
"creating_your_organization": "Δημιουργία του οργανισμού σας",
|
||||
"organization_onboarding_already_completed": "Η εισαγωγή οργανισμού έχει ήδη ολοκληρωθεί",
|
||||
"organization_onboarding_already_exists": "Η εισαγωγή οργανισμού υπάρχει ήδη",
|
||||
"organization_onboarding_not_found": "Η εισαγωγή οργανισμού δεν βρέθηκε",
|
||||
"payment_successful": "Επιτυχής πληρωμή",
|
||||
"handover_onboarding_page_title": "Παράδοση εισαγωγής",
|
||||
"handover_onboarding_page_description": "Παράδοση εισαγωγής στον χρήστη",
|
||||
"organization_already_exists_with_this_slug": "Υπάρχει ήδη οργανισμός με αυτό το slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Δεν έχετε άδεια να δημιουργήσετε οργανισμό για αυτό το email",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Δεν έχετε άδεια να μεταφέρετε μία ή περισσότερες από τις ομάδες",
|
||||
"organization_has_subscription_already": "Ο οργανισμός έχει ήδη συνδρομή",
|
||||
"rr_reset_interval": "Διάστημα επαναφοράς Round Robin",
|
||||
"interval": "Διάστημα",
|
||||
"rr_reset_interval_description": "Καθορίζει πόσο συχνά επαναφέρεται ο μετρητής κρατήσεων round robin για να διασφαλιστεί η ισορροπημένη κατανομή.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Disabled",
|
||||
"disable": "Disable",
|
||||
"billing": "Billing",
|
||||
"here": "here",
|
||||
"manage_your_billing_info": "Manage your billing information and cancel your subscription.",
|
||||
"availability": "Availability",
|
||||
"edit_availability": "Edit availability",
|
||||
@@ -1117,7 +1118,8 @@
|
||||
"duplicate": "Duplicate",
|
||||
"offer_seats": "Offer seats",
|
||||
"offer_seats_description": "Offer seats for booking. This automatically disables guest & opt-in bookings.",
|
||||
"seats_available_other": "available",
|
||||
"seats_available_one": "Seat available",
|
||||
"seats_available_other": "Seats available",
|
||||
"seats_nearly_full": "Seats almost full",
|
||||
"seats_half_full": "Seats filling fast",
|
||||
"number_of_seats": "Number of seats per booking",
|
||||
@@ -1548,6 +1550,7 @@
|
||||
"transcript_from_previous_call": "Transcript from your recent call on {{appName}} is ready to download. Links are valid only for 1 Hour",
|
||||
"you_can_download_transcript_from_attachments": "You can also download transcript from attachments",
|
||||
"link_valid_for_12_hrs": "Note: The download link is valid only for 12 hours. You can generate new download link by following instructions <1>here</1>.",
|
||||
"link_valid_for_12_hrs_description": "Note: The download link is valid only for 12 hours. You can generate new download link by following instructionss.",
|
||||
"create_your_first_form": "Create your first form",
|
||||
"create_your_first_form_description": "With Routing Forms you can ask qualifying questions and route to the correct person or event type.",
|
||||
"create_your_first_webhook": "Create your first Webhook",
|
||||
@@ -2937,6 +2940,7 @@
|
||||
"dry_run_mode_active": "You are doing a test booking.",
|
||||
"icon_showcase": "Icon showcase",
|
||||
"icons_showcase": "Icons showcase",
|
||||
"migrating_from_team":"Migrating from team",
|
||||
"feature_currently_disabled": "Feature is currently disabled",
|
||||
"choose_an_option": "Choose an option",
|
||||
"enter_option_value": "Enter option value",
|
||||
@@ -2966,6 +2970,32 @@
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email_change": "Verify email change",
|
||||
"organization_slug_taken": "Organization slug is already taken",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "You cannot create an organization as you are already a part of an organization",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "You need to complete user onboarding before creating an organization",
|
||||
"use_company_email_to_create_an_organization": "Use company email to create an organization",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "You cannot create a platform organization as you are already a part of a team",
|
||||
"you_need_to_have_minimum_published_teams": "You need to have minimum published teams",
|
||||
"you_are_part_of_this_organization_already": "You are part of this organization already",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "You are part of another organization, cannot create a new organization",
|
||||
"organization_payment_success": "Organization payment success",
|
||||
"organization_payment_success_description": "Your organization has been created successfully",
|
||||
"this_may_take_a_few_seconds": "This may take a few seconds...",
|
||||
"organization_onboarding_status": "Organization onboarding status",
|
||||
"organization_onboarding_status_description": "Organization onboarding status description",
|
||||
"payment_failed": "Payment failed",
|
||||
"payment_failed_description": "Your payment has failed. Please try again.",
|
||||
"creating_your_organization": "Creating your organization",
|
||||
"organization_onboarding_already_completed": "Organization onboarding already completed",
|
||||
"organization_onboarding_already_exists": "Organization onboarding already exists",
|
||||
"organization_onboarding_not_found": "Organization onboarding not found",
|
||||
"payment_successful": "Payment successful",
|
||||
"handover_onboarding_page_title": "Handover onboarding",
|
||||
"handover_onboarding_page_description": "Handover onboarding to the user",
|
||||
"organization_already_exists_with_this_slug": "Organization already exists with this slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "You do not have permission to create an organization for this email",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "You do not have permission to migrate one or more of the teams",
|
||||
"organization_has_subscription_already": "Organization has a subscription already",
|
||||
"rr_reset_interval": "Round Robin Reset Interval",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Determines how often the round robin booking count resets to ensure balanced distribution.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Deshabilitado",
|
||||
"disable": "Deshabilitar",
|
||||
"billing": "Facturación",
|
||||
"here": "aquí",
|
||||
"manage_your_billing_info": "Gestiona tu información de facturación y cancela tu suscripción.",
|
||||
"availability": "Disponibilidad",
|
||||
"edit_availability": "Editar disponibilidad",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "La transcripción de tu llamada reciente en {{appName}} está lista para descargar. Los enlaces son válidos solo por 1 hora",
|
||||
"you_can_download_transcript_from_attachments": "También puedes descargar la transcripción desde los archivos adjuntos",
|
||||
"link_valid_for_12_hrs": "Nota: El enlace de descarga es válido solo por 12 horas. Puedes generar un nuevo enlace de descarga siguiendo las instrucciones <1>aquí</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: El enlace de descarga es válido solo por 12 horas. Puedes generar un nuevo enlace de descarga siguiendo las instrucciones.",
|
||||
"create_your_first_form": "Crea tu primer formulario",
|
||||
"create_your_first_form_description": "Con los Formularios de Enrutamiento puedes hacer preguntas de calificación y dirigir a la persona o tipo de evento correcto.",
|
||||
"create_your_first_webhook": "Crea tu primer Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Estás haciendo una reserva de prueba.",
|
||||
"icon_showcase": "Muestra de íconos",
|
||||
"icons_showcase": "Muestra de íconos",
|
||||
"migrating_from_team": "Migrando desde el equipo",
|
||||
"feature_currently_disabled": "La función está desactivada actualmente",
|
||||
"choose_an_option": "Elige una opción",
|
||||
"enter_option_value": "Ingresa el valor de la opción",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email_change": "Verificar cambio de correo electrónico",
|
||||
"organization_slug_taken": "El slug de la organización ya está en uso",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "No puedes crear una organización ya que ya eres parte de una organización",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Necesitas completar la incorporación de usuario antes de crear una organización",
|
||||
"use_company_email_to_create_an_organization": "Usa el correo electrónico de la empresa para crear una organización",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "No puedes crear una organización de plataforma ya que ya eres parte de un equipo",
|
||||
"you_need_to_have_minimum_published_teams": "Necesitas tener un mínimo de equipos publicados",
|
||||
"you_are_part_of_this_organization_already": "Ya eres parte de esta organización",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Eres parte de otra organización, no puedes crear una nueva organización",
|
||||
"organization_payment_success": "Pago de la organización exitoso",
|
||||
"organization_payment_success_description": "Tu organización ha sido creada exitosamente",
|
||||
"this_may_take_a_few_seconds": "Esto puede tomar unos segundos...",
|
||||
"organization_onboarding_status": "Estado de incorporación de la organización",
|
||||
"organization_onboarding_status_description": "Descripción del estado de incorporación de la organización",
|
||||
"payment_failed": "El pago falló",
|
||||
"payment_failed_description": "Tu pago ha fallado. Por favor, inténtalo de nuevo.",
|
||||
"creating_your_organization": "Creando tu organización",
|
||||
"organization_onboarding_already_completed": "La incorporación de la organización ya se completó",
|
||||
"organization_onboarding_already_exists": "La incorporación de la organización ya existe",
|
||||
"organization_onboarding_not_found": "No se encontró la incorporación de la organización",
|
||||
"payment_successful": "Pago exitoso",
|
||||
"handover_onboarding_page_title": "Traspaso de incorporación",
|
||||
"handover_onboarding_page_description": "Traspaso de incorporación al usuario",
|
||||
"organization_already_exists_with_this_slug": "Ya existe una organización con este slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "No tienes permiso para crear una organización con este correo electrónico",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "No tienes permiso para migrar uno o más de los equipos",
|
||||
"organization_has_subscription_already": "La organización ya tiene una suscripción",
|
||||
"rr_reset_interval": "Intervalo de reinicio de Round Robin",
|
||||
"interval": "Intervalo",
|
||||
"rr_reset_interval_description": "Determina con qué frecuencia se reinicia el conteo de reservas de round robin para asegurar una distribución equilibrada.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Desactivado",
|
||||
"disable": "Deshabilitar",
|
||||
"billing": "Facturación",
|
||||
"here": "aquí",
|
||||
"manage_your_billing_info": "Gestione su información de facturación y cancele su suscripción.",
|
||||
"availability": "Disponibilidad",
|
||||
"edit_availability": "Editar disponibilidad",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "La transcripción de su llamada reciente en {{appName}} está lista para descargar. Los enlaces son válidos solo por 1 hora.",
|
||||
"you_can_download_transcript_from_attachments": "También puedes descargar la transcripción desde los archivos adjuntos",
|
||||
"link_valid_for_12_hrs": "Nota: El enlace de descarga es válido solo por 12 horas. Puede generar un nuevo enlace de descarga siguiendo las instrucciones <1>aquí</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: El enlace de descarga es válido solo por 12 horas. Puedes generar un nuevo enlace de descarga siguiendo las instrucciones.",
|
||||
"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.",
|
||||
"create_your_first_webhook": "Crea tu primer Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Estás haciendo una reserva de prueba.",
|
||||
"icon_showcase": "Muestra de iconos",
|
||||
"icons_showcase": "Muestra de iconos",
|
||||
"migrating_from_team": "Migrando desde el equipo",
|
||||
"feature_currently_disabled": "La función está actualmente desactivada",
|
||||
"choose_an_option": "Elige una opción",
|
||||
"enter_option_value": "Ingresa el valor de la opción",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email_change": "Verificar cambio de correo electrónico",
|
||||
"organization_slug_taken": "El slug de la organización ya está en uso",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "No puedes crear una organización ya que ya formas parte de una",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Necesitas completar la incorporación de usuario antes de crear una organización",
|
||||
"use_company_email_to_create_an_organization": "Usa el correo electrónico de la empresa para crear una organización",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "No puedes crear una organización de plataforma ya que ya formas parte de un equipo",
|
||||
"you_need_to_have_minimum_published_teams": "Necesitas tener un mínimo de equipos publicados",
|
||||
"you_are_part_of_this_organization_already": "Ya formas parte de esta organización",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Formas parte de otra organización, no puedes crear una nueva",
|
||||
"organization_payment_success": "Pago de la organización exitoso",
|
||||
"organization_payment_success_description": "Tu organización se ha creado con éxito",
|
||||
"this_may_take_a_few_seconds": "Esto puede tardar unos segundos...",
|
||||
"organization_onboarding_status": "Estado de incorporación de la organización",
|
||||
"organization_onboarding_status_description": "Descripción del estado de incorporación de la organización",
|
||||
"payment_failed": "El pago ha fallado",
|
||||
"payment_failed_description": "Tu pago ha fallado. Por favor, inténtalo de nuevo.",
|
||||
"creating_your_organization": "Creando tu organización",
|
||||
"organization_onboarding_already_completed": "La incorporación de la organización ya se ha completado",
|
||||
"organization_onboarding_already_exists": "La incorporación de la organización ya existe",
|
||||
"organization_onboarding_not_found": "No se encontró la incorporación de la organización",
|
||||
"payment_successful": "Pago exitoso",
|
||||
"handover_onboarding_page_title": "Traspaso de incorporación",
|
||||
"handover_onboarding_page_description": "Traspaso de incorporación al usuario",
|
||||
"organization_already_exists_with_this_slug": "Ya existe una organización con este slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "No tienes permiso para crear una organización con este correo electrónico",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "No tienes permiso para migrar uno o más de los equipos",
|
||||
"organization_has_subscription_already": "La organización ya tiene una suscripción",
|
||||
"rr_reset_interval": "Intervalo de reinicio de rotación",
|
||||
"interval": "Intervalo",
|
||||
"rr_reset_interval_description": "Determina con qué frecuencia se reinicia el conteo de reservas de rotación para asegurar una distribución equilibrada.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Puuetega",
|
||||
"disable": "Keela",
|
||||
"billing": "Arveldamine",
|
||||
"here": "siin",
|
||||
"manage_your_billing_info": "Hallake oma arveldusinfot ja tühistage tellimus.",
|
||||
"availability": "Saadaval",
|
||||
"edit_availability": "Muuda saadavust",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Teie hiljutise kõne transkriptsioon rakenduses {{appName}} on allalaadimiseks valmis. Lingid kehtivad ainult 1 tund",
|
||||
"you_can_download_transcript_from_attachments": "Transkriptsiooni saate alla laadida ka manustest",
|
||||
"link_valid_for_12_hrs": "Märkus. Allalaadimislink kehtib ainult 12 tundi. Uue allalaadimislingi saate luua, järgides <1>siin</1> juhiseid.",
|
||||
"link_valid_for_12_hrs_description": "Märkus: Allalaadimislink kehtib ainult 12 tundi. Uue allalaadimislingi saate genereerida juhiseid järgides.",
|
||||
"create_your_first_form": "Loo oma esimene vorm",
|
||||
"create_your_first_form_description": "Marsruutimisvormide abil saate esitada kvalifitseeruvaid küsimusi ja suunata õige inimese või sündmuse tüübi.",
|
||||
"create_your_first_webhook": "Loo oma esimene veebihaak",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Teed proovibroneeringut.",
|
||||
"icon_showcase": "Ikoonide ülevaade",
|
||||
"icons_showcase": "Ikoonide ülevaade",
|
||||
"migrating_from_team": "Meeskonnast migreerimine",
|
||||
"feature_currently_disabled": "Funktsioon on praegu välja lülitatud",
|
||||
"choose_an_option": "Vali valik",
|
||||
"enter_option_value": "Sisesta valiku väärtus",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Kasvav",
|
||||
"desc": "Kahanev",
|
||||
"verify_email_change": "Kinnita e-posti aadressi muutmine",
|
||||
"organization_slug_taken": "Organisatsiooni lühilink on juba kasutusel",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Te ei saa luua organisatsiooni, kuna olete juba osa organisatsioonist",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Enne organisatsiooni loomist peate lõpetama kasutaja liitumisprotsessi",
|
||||
"use_company_email_to_create_an_organization": "Kasutage organisatsiooni loomiseks ettevõtte e-posti",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Te ei saa luua platvormi organisatsiooni, kuna olete juba osa meeskonnast",
|
||||
"you_need_to_have_minimum_published_teams": "Teil peab olema minimaalne arv avaldatud meeskondi",
|
||||
"you_are_part_of_this_organization_already": "Te olete juba selle organisatsiooni liige",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Te olete osa teisest organisatsioonist, uut organisatsiooni ei saa luua",
|
||||
"organization_payment_success": "Organisatsiooni makse õnnestus",
|
||||
"organization_payment_success_description": "Teie organisatsioon on edukalt loodud",
|
||||
"this_may_take_a_few_seconds": "See võib võtta mõne sekundi...",
|
||||
"organization_onboarding_status": "Organisatsiooni liitumisprotsessi staatus",
|
||||
"organization_onboarding_status_description": "Organisatsiooni liitumisprotsessi staatuse kirjeldus",
|
||||
"payment_failed": "Makse ebaõnnestus",
|
||||
"payment_failed_description": "Teie makse ebaõnnestus. Palun proovige uuesti.",
|
||||
"creating_your_organization": "Teie organisatsiooni loomine",
|
||||
"organization_onboarding_already_completed": "Organisatsiooni liitumisprotsess on juba lõpetatud",
|
||||
"organization_onboarding_already_exists": "Organisatsiooni liitumisprotsess on juba olemas",
|
||||
"organization_onboarding_not_found": "Organisatsiooni liitumisprotsessi ei leitud",
|
||||
"payment_successful": "Makse õnnestus",
|
||||
"handover_onboarding_page_title": "Liitumisprotsessi üleandmine",
|
||||
"handover_onboarding_page_description": "Liitumisprotsessi üleandmine kasutajale",
|
||||
"organization_already_exists_with_this_slug": "Selle lühilingiga organisatsioon on juba olemas",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Teil pole luba selle e-posti aadressiga organisatsiooni loomiseks",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Teil pole luba ühe või mitme meeskonna migreerimiseks",
|
||||
"organization_has_subscription_already": "Organisatsioonil on juba tellimus",
|
||||
"rr_reset_interval": "Round Robini lähtestamise intervall",
|
||||
"interval": "Intervall",
|
||||
"rr_reset_interval_description": "Määrab, kui tihti round robini broneeringute arv lähtestatakse, et tagada tasakaalustatud jaotus.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Ezgaituta",
|
||||
"disable": "Ezgaitu",
|
||||
"billing": "Fakturazioa",
|
||||
"here": "hemen",
|
||||
"manage_your_billing_info": "Kudeatu zure fakturaziorako informazioa eta amaitu zure harpidetza.",
|
||||
"availability": "Eskuragarritasuna",
|
||||
"edit_availability": "Editatu eskuragarritasuna",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "{{appName}}-en egin berri duzun deiaren transkripzioa deskargatzeko prest dago. Estekak ordubetez bakarrik dira baliozkoak",
|
||||
"you_can_download_transcript_from_attachments": "Transkripzioa eranskinetan ere deskarga dezakezu",
|
||||
"link_valid_for_12_hrs": "Oharra: Deskarga esteka 12 orduz bakarrik da baliozkoa. Deskarga esteka berria sortu dezakezu <1>hemen</1> dauden argibideak jarraituz.",
|
||||
"link_valid_for_12_hrs_description": "Oharra: Deskargatzeko esteka 12 orduz bakarrik da baliozkoa. Deskargatzeko esteka berria sortu dezakezu jarraibideak jarraituz.",
|
||||
"create_your_first_form": "Sortu zure lehen galdetegia",
|
||||
"create_your_first_form_description": "Bideratze-formularioekin galdera kalifikatzaileak egin eta pertsona edo ekitaldi mota egokira bideratu dezakezu.",
|
||||
"create_your_first_webhook": "Sortu zure lehen Webhookea",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Proba-erreserba bat egiten ari zara.",
|
||||
"icon_showcase": "Ikonoen erakusleihoa",
|
||||
"icons_showcase": "Ikonoen erakusleihoa",
|
||||
"migrating_from_team": "Taldetik migratzen",
|
||||
"feature_currently_disabled": "Eginbidea desgaituta dago",
|
||||
"choose_an_option": "Aukeratu aukera bat",
|
||||
"enter_option_value": "Sartu aukeraren balioa",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Gorantz",
|
||||
"desc": "Beherantz",
|
||||
"verify_email_change": "Egiaztatu posta elektronikoaren aldaketa",
|
||||
"organization_slug_taken": "Erakundearen slug-a dagoeneko hartuta dago",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Ezin duzu erakunde bat sortu dagoeneko erakunde baten parte zarelako",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Erabiltzailearen hasierako prozesua amaitu behar duzu erakunde bat sortu aurretik",
|
||||
"use_company_email_to_create_an_organization": "Erabili enpresaren posta elektronikoa erakunde bat sortzeko",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Ezin duzu plataformako erakunde bat sortu dagoeneko talde baten parte zarelako",
|
||||
"you_need_to_have_minimum_published_teams": "Argitaratutako gutxieneko talde kopurua izan behar duzu",
|
||||
"you_are_part_of_this_organization_already": "Dagoeneko erakunde honen parte zara",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Beste erakunde baten parte zara, ezin duzu erakunde berri bat sortu",
|
||||
"organization_payment_success": "Erakundearen ordainketa arrakastatsua",
|
||||
"organization_payment_success_description": "Zure erakundea arrakastaz sortu da",
|
||||
"this_may_take_a_few_seconds": "Honek segundo batzuk har ditzake...",
|
||||
"organization_onboarding_status": "Erakundearen hasierako prozesuaren egoera",
|
||||
"organization_onboarding_status_description": "Erakundearen hasierako prozesuaren egoeraren deskribapena",
|
||||
"payment_failed": "Ordainketak huts egin du",
|
||||
"payment_failed_description": "Zure ordainketak huts egin du. Mesedez, saiatu berriro.",
|
||||
"creating_your_organization": "Zure erakundea sortzen",
|
||||
"organization_onboarding_already_completed": "Erakundearen hasierako prozesua dagoeneko amaituta dago",
|
||||
"organization_onboarding_already_exists": "Erakundearen hasierako prozesua dagoeneko existitzen da",
|
||||
"organization_onboarding_not_found": "Erakundearen hasierako prozesua ez da aurkitu",
|
||||
"payment_successful": "Ordainketa arrakastatsua",
|
||||
"handover_onboarding_page_title": "Hasierako prozesuaren eskualdaketa",
|
||||
"handover_onboarding_page_description": "Hasierako prozesua erabiltzaileari eskualdatu",
|
||||
"organization_already_exists_with_this_slug": "Erakunde bat dagoeneko existitzen da slug honekin",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Ez duzu baimenik erakunde bat sortzeko helbide elektroniko honentzat",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Ez duzu baimenik talde bat edo gehiago migratzeko",
|
||||
"organization_has_subscription_already": "Erakundeak dagoeneko harpidetza bat du",
|
||||
"rr_reset_interval": "Round Robin berrezartzeko tartea",
|
||||
"interval": "Tartea",
|
||||
"rr_reset_interval_description": "Zehazten du zenbatero berrezartzen den round robin erreserben zenbaketa, banaketa orekatua ziurtatzeko.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Pois käytöstä",
|
||||
"disable": "Poista käytöstä",
|
||||
"billing": "Laskutus",
|
||||
"here": "tässä",
|
||||
"manage_your_billing_info": "Hallinnoi laskutustietojasi ja peruuta tilauksesi.",
|
||||
"availability": "Saatavuus",
|
||||
"edit_availability": "Muokkaa saatavuutta",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Litterointi viimeisimmästä {{appName}}-puhelustasi on valmis ladattavaksi. Linkit ovat voimassa vain tunnin",
|
||||
"you_can_download_transcript_from_attachments": "Voit myös ladata muistion liitteistä",
|
||||
"link_valid_for_12_hrs": "Huom: Latauslinkki on voimassa vain 12 tuntia. Voit luoda uuden latauslinkin seuraamalla ohjeita <1>täältä</1>.",
|
||||
"link_valid_for_12_hrs_description": "Huomaa: Latauslinkki on voimassa vain 12 tuntia. Voit luoda uuden latauslinkin noudattamalla ohjeita.",
|
||||
"create_your_first_form": "Luo ensimmäinen lomakkeesi",
|
||||
"create_your_first_form_description": "Reitityslomakkeiden avulla voit esittää tarkentavia kysymyksiä ja ohjata oikealle henkilölle tai tapahtumatyyppiin",
|
||||
"create_your_first_webhook": "Luo ensimmäinen webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Teet testikäyntivarausta.",
|
||||
"icon_showcase": "Kuvakegalleria",
|
||||
"icons_showcase": "Kuvakegalleria",
|
||||
"migrating_from_team": "Siirtyminen tiimistä",
|
||||
"feature_currently_disabled": "Ominaisuus on tällä hetkellä pois käytöstä",
|
||||
"choose_an_option": "Valitse vaihtoehto",
|
||||
"enter_option_value": "Syötä vaihtoehdon arvo",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Nouseva",
|
||||
"desc": "Laskeva",
|
||||
"verify_email_change": "Vahvista sähköpostin muutos",
|
||||
"organization_slug_taken": "Organisaation lyhytnimi on jo käytössä",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Et voi luoda organisaatiota, koska olet jo osa organisaatiota",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Sinun täytyy suorittaa käyttäjän perehdytys loppuun ennen organisaation luomista",
|
||||
"use_company_email_to_create_an_organization": "Käytä yrityksen sähköpostiosoitetta organisaation luomiseen",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Et voi luoda alustaorganisaatiota, koska olet jo osa tiimiä",
|
||||
"you_need_to_have_minimum_published_teams": "Sinulla täytyy olla vähimmäismäärä julkaistuja tiimejä",
|
||||
"you_are_part_of_this_organization_already": "Olet jo osa tätä organisaatiota",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Olet osa toista organisaatiota, et voi luoda uutta organisaatiota",
|
||||
"organization_payment_success": "Organisaation maksu onnistui",
|
||||
"organization_payment_success_description": "Organisaatiosi on luotu onnistuneesti",
|
||||
"this_may_take_a_few_seconds": "Tämä saattaa kestää muutaman sekunnin...",
|
||||
"organization_onboarding_status": "Organisaation perehdytyksen tila",
|
||||
"organization_onboarding_status_description": "Organisaation perehdytyksen tilan kuvaus",
|
||||
"payment_failed": "Maksu epäonnistui",
|
||||
"payment_failed_description": "Maksusi epäonnistui. Yritä uudelleen.",
|
||||
"creating_your_organization": "Luodaan organisaatiotasi",
|
||||
"organization_onboarding_already_completed": "Organisaation perehdytys on jo suoritettu",
|
||||
"organization_onboarding_already_exists": "Organisaation perehdytys on jo olemassa",
|
||||
"organization_onboarding_not_found": "Organisaation perehdytystä ei löydy",
|
||||
"payment_successful": "Maksu onnistui",
|
||||
"handover_onboarding_page_title": "Perehdytyksen luovutus",
|
||||
"handover_onboarding_page_description": "Perehdytyksen luovutus käyttäjälle",
|
||||
"organization_already_exists_with_this_slug": "Organisaatio on jo olemassa tällä verkko-osoitteella",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Sinulla ei ole oikeutta luoda organisaatiota tälle sähköpostiosoitteelle",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Sinulla ei ole oikeutta siirtää yhtä tai useampaa tiimiä",
|
||||
"organization_has_subscription_already": "Organisaatiolla on jo tilaus",
|
||||
"rr_reset_interval": "Round Robin -nollausväli",
|
||||
"interval": "Aikaväli",
|
||||
"rr_reset_interval_description": "Määrittää, kuinka usein round robin -varauslaskuri nollataan tasapainoisen jakelun varmistamiseksi.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Désactivé",
|
||||
"disable": "Désactiver",
|
||||
"billing": "Facturation",
|
||||
"here": "ici",
|
||||
"manage_your_billing_info": "Gérez vos informations de facturation et annulez votre abonnement.",
|
||||
"availability": "Disponibilités",
|
||||
"edit_availability": "Modifier les disponibilités",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "La transcription de votre récent appel sur {{appName}} est prête à être téléchargée. Les liens ne sont valides que pendant 1 heure",
|
||||
"you_can_download_transcript_from_attachments": "Vous pouvez également télécharger la transcription depuis les pièces jointes",
|
||||
"link_valid_for_12_hrs": "Remarque : le lien de téléchargement n'est valide que pendant 12 heures. Vous pouvez générer un nouveau lien de téléchargement en suivant les instructions <1>ici</1>.",
|
||||
"link_valid_for_12_hrs_description": "Remarque : le lien de téléchargement n'est valable que pendant 12 heures. Vous pouvez générer un nouveau lien de téléchargement en suivant les instructions.",
|
||||
"create_your_first_form": "Créez votre premier formulaire",
|
||||
"create_your_first_form_description": "Avec les formulaires de routage, vous pouvez poser des questions de qualification et rediriger vers la bonne personne ou le bon type d'événement.",
|
||||
"create_your_first_webhook": "Créez votre premier webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Vous effectuez une réservation test.",
|
||||
"icon_showcase": "Présentation des icônes",
|
||||
"icons_showcase": "Présentation des icônes",
|
||||
"migrating_from_team": "Migration depuis l'équipe",
|
||||
"feature_currently_disabled": "La fonctionnalité est actuellement désactivée",
|
||||
"choose_an_option": "Choisir une option",
|
||||
"enter_option_value": "Saisir la valeur de l'option",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email_change": "Vérifier le changement d'e-mail",
|
||||
"organization_slug_taken": "L'identifiant de l'organisation est déjà pris",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Vous ne pouvez pas créer une organisation car vous faites déjà partie d'une organisation",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Vous devez terminer l'intégration utilisateur avant de créer une organisation",
|
||||
"use_company_email_to_create_an_organization": "Utilisez l'e-mail de l'entreprise pour créer une organisation",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Vous ne pouvez pas créer une organisation plateforme car vous faites déjà partie d'une équipe",
|
||||
"you_need_to_have_minimum_published_teams": "Vous devez avoir un minimum d'équipes publiées",
|
||||
"you_are_part_of_this_organization_already": "Vous faites déjà partie de cette organisation",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Vous faites partie d'une autre organisation, impossible de créer une nouvelle organisation",
|
||||
"organization_payment_success": "Paiement de l'organisation réussi",
|
||||
"organization_payment_success_description": "Votre organisation a été créée avec succès",
|
||||
"this_may_take_a_few_seconds": "Cela peut prendre quelques secondes...",
|
||||
"organization_onboarding_status": "Statut d'intégration de l'organisation",
|
||||
"organization_onboarding_status_description": "Description du statut d'intégration de l'organisation",
|
||||
"payment_failed": "Le paiement a échoué",
|
||||
"payment_failed_description": "Votre paiement a échoué. Veuillez réessayer.",
|
||||
"creating_your_organization": "Création de votre organisation",
|
||||
"organization_onboarding_already_completed": "L'intégration de l'organisation est déjà terminée",
|
||||
"organization_onboarding_already_exists": "L'intégration de l'organisation existe déjà",
|
||||
"organization_onboarding_not_found": "Intégration de l'organisation non trouvée",
|
||||
"payment_successful": "Paiement réussi",
|
||||
"handover_onboarding_page_title": "Transfert de l'intégration",
|
||||
"handover_onboarding_page_description": "Transfert de l'intégration à l'utilisateur",
|
||||
"organization_already_exists_with_this_slug": "Une organisation existe déjà avec ce slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Vous n'avez pas la permission de créer une organisation pour cet e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Vous n'avez pas la permission de migrer une ou plusieurs des équipes",
|
||||
"organization_has_subscription_already": "L'organisation a déjà un abonnement",
|
||||
"rr_reset_interval": "Intervalle de réinitialisation du round-robin",
|
||||
"interval": "Intervalle",
|
||||
"rr_reset_interval_description": "Détermine la fréquence à laquelle le compteur de réservations round-robin se réinitialise pour assurer une distribution équilibrée.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "מושבת",
|
||||
"disable": "השבת",
|
||||
"billing": "חיוב",
|
||||
"here": "כאן",
|
||||
"manage_your_billing_info": "נהל את פרטי החיוב ובטל את המינוי.",
|
||||
"availability": "זמינות",
|
||||
"edit_availability": "עריכת נתוני זמינות",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "תמלול השיחה האחרונה שלך ב־{{appName}} זמין להורדה. קישורים תקפים למשך שעה בלבד",
|
||||
"you_can_download_transcript_from_attachments": "ניתן גם להוריד את התמליל מהקבצים המצורפים",
|
||||
"link_valid_for_12_hrs": "לתשומת ליבך: קישור ההורדה תקף רק למשך 12 שעות. אפשר לייצר קישור הורדה חדש על ידי מעקב אחר ההוראות <1>שכאן</1>.",
|
||||
"link_valid_for_12_hrs_description": "הערה: קישור ההורדה תקף רק למשך 12 שעות. ניתן ליצור קישור הורדה חדש על ידי מעקב אחר ההוראות.",
|
||||
"create_your_first_form": "צור/צרי את הטופס הראשון שלך",
|
||||
"create_your_first_form_description": "באמצעות טפסי ניתוב ניתן לשאול שאלות סיווג ולנתב אל האדם או אל סוג האירוע המתאימים.",
|
||||
"create_your_first_webhook": "יצירת ה-Webhook הראשון שלך",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "אתה מבצע הזמנת ניסיון.",
|
||||
"icon_showcase": "תצוגת אייקון",
|
||||
"icons_showcase": "תצוגת אייקונים",
|
||||
"migrating_from_team": "מעבר מצוות",
|
||||
"feature_currently_disabled": "התכונה מושבתת כרגע",
|
||||
"choose_an_option": "בחר אפשרות",
|
||||
"enter_option_value": "הזן ערך אפשרות",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "סדר עולה",
|
||||
"desc": "סדר יורד",
|
||||
"verify_email_change": "אימות שינוי כתובת דוא\"ל",
|
||||
"organization_slug_taken": "כתובת הארגון כבר תפוסה",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "אינך יכול ליצור ארגון מכיוון שאתה כבר חלק מארגון",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "עליך להשלים את תהליך הקליטה למשתמש לפני יצירת ארגון",
|
||||
"use_company_email_to_create_an_organization": "השתמש בדוא\"ל החברה כדי ליצור ארגון",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "אינך יכול ליצור ארגון פלטפורמה מכיוון שאתה כבר חלק מצוות",
|
||||
"you_need_to_have_minimum_published_teams": "עליך להיות בעל מספר מינימלי של צוותים מפורסמים",
|
||||
"you_are_part_of_this_organization_already": "אתה כבר חלק מארגון זה",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "אתה חלק מארגון אחר, לא ניתן ליצור ארגון חדש",
|
||||
"organization_payment_success": "תשלום הארגון הצליח",
|
||||
"organization_payment_success_description": "הארגון שלך נוצר בהצלחה",
|
||||
"this_may_take_a_few_seconds": "זה עשוי לקחת מספר שניות...",
|
||||
"organization_onboarding_status": "סטטוס קליטת הארגון",
|
||||
"organization_onboarding_status_description": "תיאור סטטוס קליטת הארגון",
|
||||
"payment_failed": "התשלום נכשל",
|
||||
"payment_failed_description": "התשלום שלך נכשל. אנא נסה שוב.",
|
||||
"creating_your_organization": "יוצר את הארגון שלך",
|
||||
"organization_onboarding_already_completed": "קליטת הארגון כבר הושלמה",
|
||||
"organization_onboarding_already_exists": "קליטת הארגון כבר קיימת",
|
||||
"organization_onboarding_not_found": "קליטת הארגון לא נמצאה",
|
||||
"payment_successful": "התשלום הצליח",
|
||||
"handover_onboarding_page_title": "העברת תהליך הקליטה",
|
||||
"handover_onboarding_page_description": "העברת תהליך הקליטה למשתמש",
|
||||
"organization_already_exists_with_this_slug": "ארגון כבר קיים עם מזהה URL זה",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "אין לך הרשאה ליצור ארגון עבור כתובת האימייל הזו",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "אין לך הרשאה להעביר אחד או יותר מהצוותים",
|
||||
"organization_has_subscription_already": "לארגון כבר יש מנוי",
|
||||
"rr_reset_interval": "מרווח איפוס סבב",
|
||||
"interval": "מרווח",
|
||||
"rr_reset_interval_description": "קובע באיזו תדירות מתאפס מונה ההזמנות בסבב כדי להבטיח חלוקה מאוזנת.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Tiltva",
|
||||
"disable": "Letiltás",
|
||||
"billing": "Számlázás",
|
||||
"here": "itt",
|
||||
"manage_your_billing_info": "Kezelje számlázási adatait, és mondja le előfizetését.",
|
||||
"availability": "Elérhetőség",
|
||||
"edit_availability": "Elérhetőség szerkesztése",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "A(z) {{appName}} nevű legutóbbi hívásának átirata letölthető. A linkek csak 1 óráig érvényesek",
|
||||
"you_can_download_transcript_from_attachments": "A jegyzőkönyvet letöltheti a csatolmányok közül",
|
||||
"link_valid_for_12_hrs": "Megjegyzés: A letöltési link csak 12 óráig érvényes. Az <1>utasításokat</1> követve hozhat létre új letöltési linket.",
|
||||
"link_valid_for_12_hrs_description": "Megjegyzés: A letöltési link csak 12 óráig érvényes. Az utasítások követésével új letöltési linket generálhat.",
|
||||
"create_your_first_form": "Hozza létre az első űrlapot",
|
||||
"create_your_first_form_description": "A Routing Forms segítségével minősítő kérdéseket tehet fel, és a megfelelő személyhez vagy eseménytípushoz irányíthat.",
|
||||
"create_your_first_webhook": "Hozza létre első Webhookját",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Tesztfoglalást végzel.",
|
||||
"icon_showcase": "Ikon bemutató",
|
||||
"icons_showcase": "Ikonok bemutatója",
|
||||
"migrating_from_team": "Csapatból való áttelepítés",
|
||||
"feature_currently_disabled": "A funkció jelenleg ki van kapcsolva",
|
||||
"choose_an_option": "Válassz egy opciót",
|
||||
"enter_option_value": "Add meg az opció értékét",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Növekvő",
|
||||
"desc": "Csökkenő",
|
||||
"verify_email_change": "E-mail-cím módosításának megerősítése",
|
||||
"organization_slug_taken": "A szervezet slug-ja már foglalt",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Nem hozhat létre szervezetet, mivel már tagja egy szervezetnek",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "A szervezet létrehozása előtt be kell fejeznie a felhasználói bevezetést",
|
||||
"use_company_email_to_create_an_organization": "Használjon céges e-mail címet a szervezet létrehozásához",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Nem hozhat létre platform szervezetet, mivel már tagja egy csapatnak",
|
||||
"you_need_to_have_minimum_published_teams": "Minimális számú közzétett csapattal kell rendelkeznie",
|
||||
"you_are_part_of_this_organization_already": "Ön már tagja ennek a szervezetnek",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Ön már tagja egy másik szervezetnek, nem hozhat létre új szervezetet",
|
||||
"organization_payment_success": "Szervezeti fizetés sikeres",
|
||||
"organization_payment_success_description": "Az Ön szervezete sikeresen létrejött",
|
||||
"this_may_take_a_few_seconds": "Ez néhány másodpercet vehet igénybe...",
|
||||
"organization_onboarding_status": "Szervezeti bevezetés állapota",
|
||||
"organization_onboarding_status_description": "Szervezeti bevezetés állapotának leírása",
|
||||
"payment_failed": "A fizetés sikertelen",
|
||||
"payment_failed_description": "A fizetés sikertelen volt. Kérjük, próbálja újra.",
|
||||
"creating_your_organization": "Az Ön szervezetének létrehozása",
|
||||
"organization_onboarding_already_completed": "A szervezeti bevezetés már befejeződött",
|
||||
"organization_onboarding_already_exists": "A szervezeti bevezetés már létezik",
|
||||
"organization_onboarding_not_found": "A szervezeti bevezetés nem található",
|
||||
"payment_successful": "A fizetés sikeres",
|
||||
"handover_onboarding_page_title": "Bevezetés átadása",
|
||||
"handover_onboarding_page_description": "Bevezetés átadása a felhasználónak",
|
||||
"organization_already_exists_with_this_slug": "Már létezik szervezet ezzel a slug-gal",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nincs jogosultsága szervezetet létrehozni ehhez az e-mail címhez",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nincs jogosultsága egy vagy több csapat migrálásához",
|
||||
"organization_has_subscription_already": "A szervezetnek már van előfizetése",
|
||||
"rr_reset_interval": "Round Robin visszaállítási időköz",
|
||||
"interval": "Időköz",
|
||||
"rr_reset_interval_description": "Meghatározza, hogy milyen gyakran állítódik vissza a round robin foglalások számlálója a kiegyensúlyozott elosztás érdekében.",
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
"emailed_host_and_attendee_recurring": "Abbiamo inviato un'email con un invito al calendario con i dettagli a tutti per il primo di questi eventi ricorrenti.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Ti incontri con {{user}}. Abbiamo inviato un'email con un invito al calendario con i dettagli a tutti per il primo di questi eventi ricorrenti.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} si incontra con {{attendee}}. Abbiamo inviato un'email con un invito al calendario con i dettagli a tutti per il primo di questi eventi ricorrenti.",
|
||||
"emailed_you_and_any_other_attendees": "Tu e tutti gli altri partecipanti siete stati inviati via email con queste informazioni.",
|
||||
"emailed_you_and_any_other_attendees": "Tu e tutti gli altri partecipanti siete stati invitati via email con queste informazioni.",
|
||||
"needs_to_be_confirmed_or_rejected": "La tua prenotazione deve ancora essere confermata o rifiutata.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "La tua riunione ricorrente deve ancora essere confermata o rifiutata.",
|
||||
"user_needs_to_confirm_or_reject_booking": "{{user}} deve ancora confermare o rifiutare la prenotazione.",
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Disabilitato",
|
||||
"disable": "Disabilitato",
|
||||
"billing": "Fatturazione",
|
||||
"here": "qui",
|
||||
"manage_your_billing_info": "Gestisci le tue informazioni di fatturazione e annulla il tuo abbonamento.",
|
||||
"availability": "Disponibilità",
|
||||
"edit_availability": "Modifica disponibilità",
|
||||
@@ -899,7 +900,7 @@
|
||||
"edit": "Modifica",
|
||||
"add_input": "Aggiungi un input",
|
||||
"disable_notes": "Nascondi le note nel calendario",
|
||||
"disable_notes_description": "Per motivi di privacy, gli input e le note aggiuntivi saranno nascosti nella voce del calendario. Verranno comunque inviati alla tua email.",
|
||||
"disable_notes_description": "Per motivi di privacy, gli input e le note aggiuntivi saranno nascosti nella voce del calendario. Verranno comunque invitati alla tua email.",
|
||||
"requires_confirmation_description": "La prenotazione deve essere confermata manualmente prima di essere inviata alle integrazioni e che venga inviata una e-mail di conferma.",
|
||||
"requires_confirmation_will_block_slot_description": "Le prenotazioni non confermate bloccano comunque gli slot del calendario.",
|
||||
"recurring_event": "Evento ricorrente",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "La trascrizione dalla tua recente chiamata su {{appName}} è pronta per essere scaricata. I link sono validi solo per 1 ora",
|
||||
"you_can_download_transcript_from_attachments": "Puoi anche scaricare la trascrizione dagli allegati",
|
||||
"link_valid_for_12_hrs": "Nota: Il link per il download è valido solo per 12 ore. Puoi generare un nuovo link di download seguendo le istruzioni <1>qui</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: il link per il download è valido solo per 12 ore. Puoi generare un nuovo link per il download seguendo le istruzioni.",
|
||||
"create_your_first_form": "Crea il tuo primo modulo",
|
||||
"create_your_first_form_description": "I Moduli di instradamento consentono di porre domande qualificanti agli utenti per indirizzarli a persone o eventi pertinenti.",
|
||||
"create_your_first_webhook": "Crea il tuo primo Webhook",
|
||||
@@ -2285,7 +2287,7 @@
|
||||
"user_has_no_app_installed": "Questo utente non ha ancora installato alcuna app",
|
||||
"requires_booker_email_verification": "Richiede la verifica dell'indirizzo e-mail della persona che prenota",
|
||||
"description_requires_booker_email_verification": "Per garantire la verifica dell'indirizzo e-mail della persona che prenota prima di panificare eventi",
|
||||
"requires_confirmation_mandatory": "I messaggi di testo possono solo essere inviati ai partecipanti quando il tipo di evento richiede una conferma.",
|
||||
"requires_confirmation_mandatory": "I messaggi di testo possono solo essere invitati ai partecipanti quando il tipo di evento richiede una conferma.",
|
||||
"organizations": "Organizzazioni",
|
||||
"upload_cal_video_logo": "Carica il logo Cal Video",
|
||||
"update_cal_video_logo": "Aggiorna il logo Cal Video",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Stai effettuando una prenotazione di prova.",
|
||||
"icon_showcase": "Galleria delle icone",
|
||||
"icons_showcase": "Galleria delle icone",
|
||||
"migrating_from_team": "Migrazione dal team",
|
||||
"feature_currently_disabled": "La funzionalità è attualmente disattivata",
|
||||
"choose_an_option": "Scegli un'opzione",
|
||||
"enter_option_value": "Inserisci il valore dell'opzione",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Crescente",
|
||||
"desc": "Decrescente",
|
||||
"verify_email_change": "Verifica la modifica dell'email",
|
||||
"organization_slug_taken": "Lo slug dell'organizzazione è già stato preso",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Non puoi creare un'organizzazione poiché fai già parte di un'organizzazione",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Devi completare l'onboarding utente prima di creare un'organizzazione",
|
||||
"use_company_email_to_create_an_organization": "Usa l'email aziendale per creare un'organizzazione",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Non puoi creare un'organizzazione piattaforma poiché fai già parte di un team",
|
||||
"you_need_to_have_minimum_published_teams": "Devi avere un numero minimo di team pubblicati",
|
||||
"you_are_part_of_this_organization_already": "Fai già parte di questa organizzazione",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Fai parte di un'altra organizzazione, non puoi creare una nuova organizzazione",
|
||||
"organization_payment_success": "Pagamento dell'organizzazione riuscito",
|
||||
"organization_payment_success_description": "La tua organizzazione è stata creata con successo",
|
||||
"this_may_take_a_few_seconds": "Questo potrebbe richiedere alcuni secondi...",
|
||||
"organization_onboarding_status": "Stato dell'onboarding dell'organizzazione",
|
||||
"organization_onboarding_status_description": "Descrizione dello stato dell'onboarding dell'organizzazione",
|
||||
"payment_failed": "Pagamento fallito",
|
||||
"payment_failed_description": "Il tuo pagamento non è andato a buon fine. Per favore, riprova.",
|
||||
"creating_your_organization": "Creazione della tua organizzazione",
|
||||
"organization_onboarding_already_completed": "Onboarding dell'organizzazione già completato",
|
||||
"organization_onboarding_already_exists": "L'onboarding dell'organizzazione esiste già",
|
||||
"organization_onboarding_not_found": "Onboarding dell'organizzazione non trovato",
|
||||
"payment_successful": "Pagamento riuscito",
|
||||
"handover_onboarding_page_title": "Passaggio di consegne dell'onboarding",
|
||||
"handover_onboarding_page_description": "Passaggio di consegne dell'onboarding all'utente",
|
||||
"organization_already_exists_with_this_slug": "Un'organizzazione con questo slug esiste già",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Non hai il permesso di creare un'organizzazione per questa email",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Non hai il permesso di migrare uno o più team",
|
||||
"organization_has_subscription_already": "L'organizzazione ha già un abbonamento",
|
||||
"rr_reset_interval": "Intervallo di reset round robin",
|
||||
"interval": "Intervallo",
|
||||
"rr_reset_interval_description": "Determina la frequenza con cui il conteggio delle prenotazioni round robin viene azzerato per garantire una distribuzione equilibrata.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "無効",
|
||||
"disable": "無効",
|
||||
"billing": "請求",
|
||||
"here": "こちら",
|
||||
"manage_your_billing_info": "請求情報の管理とサブスクリプションのキャンセル。",
|
||||
"availability": "利用可能期間",
|
||||
"edit_availability": "参加可能な時間を編集",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "{{appName}}での最近の通話のトランスクリプトがダウンロード可能です。リンクは1時間のみ有効です。",
|
||||
"you_can_download_transcript_from_attachments": "添付ファイルから議事録をダウンロードすることもできます",
|
||||
"link_valid_for_12_hrs": "注意: ダウンロードリンクは12時間のみ有効です。新しいダウンロードリンクを生成するには、<1>こちら</1>の指示に従ってください。",
|
||||
"link_valid_for_12_hrs_description": "注意:ダウンロードリンクの有効期限は12時間です。指示に従って新しいダウンロードリンクを生成できます。",
|
||||
"create_your_first_form": "最初のフォームを作成",
|
||||
"create_your_first_form_description": "ルーティングフォームを使用すれば、絞り込みの質問を通して適切な人物やイベントの種類へとルーティングを行うことができます。",
|
||||
"create_your_first_webhook": "最初のウェブフックを作成",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "テスト予約を実行中です。",
|
||||
"icon_showcase": "アイコンショーケース",
|
||||
"icons_showcase": "アイコンショーケース",
|
||||
"migrating_from_team": "チームから移行中",
|
||||
"feature_currently_disabled": "この機能は現在無効になっています",
|
||||
"choose_an_option": "オプションを選択",
|
||||
"enter_option_value": "オプション値を入力",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "昇順",
|
||||
"desc": "降順",
|
||||
"verify_email_change": "メールアドレスの変更を確認",
|
||||
"organization_slug_taken": "組織のスラッグはすでに使用されています",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "すでに組織に所属しているため、新しい組織を作成することはできません",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "組織を作成する前にユーザーオンボーディングを完了する必要があります",
|
||||
"use_company_email_to_create_an_organization": "組織を作成するには会社のメールアドレスを使用してください",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "すでにチームに所属しているため、プラットフォーム組織を作成することはできません",
|
||||
"you_need_to_have_minimum_published_teams": "最低限の公開済みチームが必要です",
|
||||
"you_are_part_of_this_organization_already": "あなたはすでにこの組織のメンバーです",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "他の組織に所属しているため、新しい組織を作成することはできません",
|
||||
"organization_payment_success": "組織の支払いが成功しました",
|
||||
"organization_payment_success_description": "組織が正常に作成されました",
|
||||
"this_may_take_a_few_seconds": "これには数秒かかる場合があります...",
|
||||
"organization_onboarding_status": "組織オンボーディングのステータス",
|
||||
"organization_onboarding_status_description": "組織オンボーディングのステータスの説明",
|
||||
"payment_failed": "支払いに失敗しました",
|
||||
"payment_failed_description": "支払いに失敗しました。もう一度お試しください。",
|
||||
"creating_your_organization": "組織を作成中",
|
||||
"organization_onboarding_already_completed": "組織オンボーディングはすでに完了しています",
|
||||
"organization_onboarding_already_exists": "組織オンボーディングはすでに存在します",
|
||||
"organization_onboarding_not_found": "組織オンボーディングが見つかりません",
|
||||
"payment_successful": "支払いが成功しました",
|
||||
"handover_onboarding_page_title": "オンボーディングの引き継ぎ",
|
||||
"handover_onboarding_page_description": "ユーザーへのオンボーディングの引き継ぎ",
|
||||
"organization_already_exists_with_this_slug": "このスラッグを持つ組織はすでに存在します",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "このメールアドレスで組織を作成する権限がありません",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "1つ以上のチームを移行する権限がありません",
|
||||
"organization_has_subscription_already": "組織はすでにサブスクリプションを持っています",
|
||||
"rr_reset_interval": "ラウンドロビンのリセット間隔",
|
||||
"interval": "間隔",
|
||||
"rr_reset_interval_description": "ラウンドロビンの予約カウントがリセットされる頻度を決定し、バランスの取れた配分を確保します。",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "បានបិទ",
|
||||
"disable": "បិទ",
|
||||
"billing": "វិក្កយបត្រ",
|
||||
"here": "នៅទីនេះ",
|
||||
"manage_your_billing_info": "គ្រប់គ្រងព័ត៌មានវិក្កយបត្រ និងបោះបង់ការជាវរបស់អ្នក។",
|
||||
"availability": "ភាពអាចប្រើបាន",
|
||||
"edit_availability": "កែសម្រួលភាពអាចប្រើបាន",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "ការបកប្រែពីការហៅថ្មីៗរបស់អ្នកនៅលើ {{appName}} ត្រូវបានត្រៀមរួចរាល់សម្រាប់ទាញយក។ តំណភ្ជាប់មានសុពលភាពតែ 1 ម៉ោងប៉ុណ្ណោះ",
|
||||
"you_can_download_transcript_from_attachments": "អ្នកក៏អាចទាញយកកំណត់ត្រាពីឯកសារភ្ជាប់បានដែរ",
|
||||
"link_valid_for_12_hrs": "ចំណាំ៖ តំណភ្ជាប់ទាញយកមានសុពលភាពតែ 12 ម៉ោងប៉ុណ្ណោះ។ អ្នកអាចបង្កើតតំណភ្ជាប់ទាញយកថ្មីដោយអនុវត្តតាមសេចក្តីណែនាំ <1>នៅទីនេះ</1>.",
|
||||
"link_valid_for_12_hrs_description": "ចំណាំ៖ តំណភ្ជាប់ទាញយកមានសុពលភាពតែ 12 ម៉ោងប៉ុណ្ណោះ។ អ្នកអាចបង្កើតតំណភ្ជាប់ទាញយកថ្មីបានដោយធ្វើតាមការណែនាំ។",
|
||||
"create_your_first_form": "បង្កើតទម្រង់ដំបូងរបស់អ្នក",
|
||||
"create_your_first_form_description": "ជាមួយនឹងទម្រង់ Routing អ្នកអាចសួរចម្លើយសមរម្យ និងបញ្ជូនទៅកាន់មនុស្សឬប្រភេទព្រឹត្តិការណ៍ត្រឹមត្រូវ។",
|
||||
"create_your_first_webhook": "បង្កើត Webhook ដំបូងរបស់អ្នក",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "អ្នកកំពុងធ្វើការកក់សាកល្បង។",
|
||||
"icon_showcase": "ការបង្ហាញរូបតំណាង",
|
||||
"icons_showcase": "ការបង្ហាញរូបតំណាងនានា",
|
||||
"migrating_from_team": "ផ្លាស់ប្តូរពីក្រុម",
|
||||
"feature_currently_disabled": "មុខងារត្រូវបានបិទដំណើរការនាពេលបច្ចុប្បន្ន",
|
||||
"choose_an_option": "ជ្រើសរើសជម្រើសមួយ",
|
||||
"enter_option_value": "បញ្ចូលតម្លៃជម្រើស",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "ឡើង",
|
||||
"desc": "ចុះ",
|
||||
"verify_email_change": "ផ្ទៀងផ្ទាត់ការផ្លាស់ប្តូរអ៊ីមែល",
|
||||
"organization_slug_taken": "ឈ្មោះសំគាល់អង្គការត្រូវបានគេប្រើរួចហើយ",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "អ្នកមិនអាចបង្កើតអង្គការបានទេ ដោយសារអ្នកជាផ្នែកមួយនៃអង្គការរួចហើយ",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "អ្នកត្រូវតែបញ្ចប់ការណែនាំអ្នកប្រើប្រាស់ថ្មីមុនពេលបង្កើតអង្គការ",
|
||||
"use_company_email_to_create_an_organization": "ប្រើអ៊ីមែលក្រុមហ៊ុនដើម្បីបង្កើតអង្គការ",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "អ្នកមិនអាចបង្កើតអង្គការវេទិកាបានទេ ដោយសារអ្នកជាផ្នែកមួយនៃក្រុមរួចហើយ",
|
||||
"you_need_to_have_minimum_published_teams": "អ្នកត្រូវមានក្រុមដែលបានបោះពុម្ពផ្សាយអប្បបរមា",
|
||||
"you_are_part_of_this_organization_already": "អ្នកជាផ្នែកមួយនៃអង្គការនេះរួចហើយ",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "អ្នកជាផ្នែកមួយនៃអង្គការផ្សេង មិនអាចបង្កើតអង្គការថ្មីបានទេ",
|
||||
"organization_payment_success": "ការទូទាត់អង្គការបានជោគជ័យ",
|
||||
"organization_payment_success_description": "អង្គការរបស់អ្នកត្រូវបានបង្កើតដោយជោគជ័យ",
|
||||
"this_may_take_a_few_seconds": "នេះអាចចំណាយពេលពីរបីវិនាទី...",
|
||||
"organization_onboarding_status": "ស្ថានភាពការណែនាំអង្គការថ្មី",
|
||||
"organization_onboarding_status_description": "ការពិពណ៌នាអំពីស្ថានភាពការណែនាំអង្គការថ្មី",
|
||||
"payment_failed": "ការទូទាត់បានបរាជ័យ",
|
||||
"payment_failed_description": "ការទូទាត់របស់អ្នកបានបរាជ័យ។ សូមព្យាយាមម្តងទៀត។",
|
||||
"creating_your_organization": "កំពុងបង្កើតអង្គការរបស់អ្នក",
|
||||
"organization_onboarding_already_completed": "ការណែនាំអង្គការថ្មីត្រូវបានបញ្ចប់រួចហើយ",
|
||||
"organization_onboarding_already_exists": "ការណែនាំអង្គការថ្មីមានរួចហើយ",
|
||||
"organization_onboarding_not_found": "រកមិនឃើញការណែនាំអង្គការថ្មីទេ",
|
||||
"payment_successful": "ការទូទាត់បានជោគជ័យ",
|
||||
"handover_onboarding_page_title": "ការផ្ទេរការណែនាំថ្មី",
|
||||
"handover_onboarding_page_description": "ផ្ទេរការណែនាំថ្មីទៅឱ្យអ្នកប្រើប្រាស់",
|
||||
"organization_already_exists_with_this_slug": "អង្គការមានរួចហើយជាមួយនឹង slug នេះ",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "អ្នកមិនមានសិទ្ធិបង្កើតអង្គការសម្រាប់អ៊ីមែលនេះទេ",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "អ្នកមិនមានសិទ្ធិផ្លាស់ប្តូរក្រុមមួយឬច្រើនទេ",
|
||||
"organization_has_subscription_already": "អង្គការមានការជាវជាប្រចាំរួចហើយ",
|
||||
"rr_reset_interval": "ចន្លោះពេលកំណត់ឡើងវិញនៃ Round Robin",
|
||||
"interval": "ចន្លោះពេល",
|
||||
"rr_reset_interval_description": "កំណត់ថាតើញឹកញាប់ប៉ុណ្ណាដែលការរាប់ការកក់ round robin ត្រូវកំណត់ឡើងវិញដើម្បីធានាការចែកចាយស្មើគ្នា។",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "비활성화",
|
||||
"disable": "비활성화",
|
||||
"billing": "청구",
|
||||
"here": "여기",
|
||||
"manage_your_billing_info": "결제 정보를 관리하고 구독을 취소하세요.",
|
||||
"availability": "유효성",
|
||||
"edit_availability": "가용성 편집",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "{{appName}}에서 최근 통화한 대화 기록이 다운로드 준비되었습니다. 링크는 1시간 동안만 유효합니다.",
|
||||
"you_can_download_transcript_from_attachments": "첨부 파일에서 대화 내용을 다운로드할 수 있습니다",
|
||||
"link_valid_for_12_hrs": "참고: 다운로드 링크는 12시간 동안만 유효합니다. <1>여기</1>의 지침을 따라 새 다운로드 링크를 생성할 수 있습니다.",
|
||||
"link_valid_for_12_hrs_description": "참고: 다운로드 링크는 12시간 동안만 유효합니다. 안내에 따라 새로운 다운로드 링크를 생성할 수 있습니다.",
|
||||
"create_your_first_form": "첫 양식 작성",
|
||||
"create_your_first_form_description": "라우팅 양식을 사용하면 적격성 질문을 올리고 올바른 사람 또는 이벤트 유형으로 라우팅할 수 있습니다.",
|
||||
"create_your_first_webhook": "첫 웹훅 생성",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "테스트 예약을 진행하고 있습니다.",
|
||||
"icon_showcase": "아이콘 쇼케이스",
|
||||
"icons_showcase": "아이콘 쇼케이스",
|
||||
"migrating_from_team": "팀에서 마이그레이션",
|
||||
"feature_currently_disabled": "현재 기능이 비활성화되어 있습니다",
|
||||
"choose_an_option": "옵션 선택",
|
||||
"enter_option_value": "옵션 값 입력",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "오름차순",
|
||||
"desc": "내림차순",
|
||||
"verify_email_change": "이메일 변경 확인",
|
||||
"organization_slug_taken": "조직 슬러그가 이미 사용 중입니다",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "이미 조직의 일원이므로 새로운 조직을 만들 수 없습니다",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "조직을 만들기 전에 사용자 온보딩을 완료해야 합니다",
|
||||
"use_company_email_to_create_an_organization": "조직을 만들려면 회사 이메일을 사용하세요",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "이미 팀의 일원이므로 플랫폼 조직을 만들 수 없습니다",
|
||||
"you_need_to_have_minimum_published_teams": "최소한의 게시된 팀이 필요합니다",
|
||||
"you_are_part_of_this_organization_already": "이미 이 조직의 일원입니다",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "다른 조직의 일원이므로 새로운 조직을 만들 수 없습니다",
|
||||
"organization_payment_success": "조직 결제 성공",
|
||||
"organization_payment_success_description": "조직이 성공적으로 생성되었습니다",
|
||||
"this_may_take_a_few_seconds": "잠시만 기다려 주세요...",
|
||||
"organization_onboarding_status": "조직 온보딩 상태",
|
||||
"organization_onboarding_status_description": "조직 온보딩 상태 설명",
|
||||
"payment_failed": "결제 실패",
|
||||
"payment_failed_description": "결제에 실패했습니다. 다시 시도해 주세요.",
|
||||
"creating_your_organization": "조직 생성 중",
|
||||
"organization_onboarding_already_completed": "조직 온보딩이 이미 완료되었습니다",
|
||||
"organization_onboarding_already_exists": "조직 온보딩이 이미 존재합니다",
|
||||
"organization_onboarding_not_found": "조직 온보딩을 찾을 수 없습니다",
|
||||
"payment_successful": "결제 성공",
|
||||
"handover_onboarding_page_title": "인수인계 온보딩",
|
||||
"handover_onboarding_page_description": "사용자에게 온보딩 인수인계",
|
||||
"organization_already_exists_with_this_slug": "이 슬러그로 이미 조직이 존재합니다",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "이 이메일로 조직을 생성할 권한이 없습니다",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "하나 이상의 팀을 마이그레이션할 권한이 없습니다",
|
||||
"organization_has_subscription_already": "조직이 이미 구독 중입니다",
|
||||
"rr_reset_interval": "라운드 로빈 재설정 간격",
|
||||
"interval": "간격",
|
||||
"rr_reset_interval_description": "균형 잡힌 분배를 보장하기 위해 라운드 로빈 예약 횟수가 얼마나 자주 재설정되는지 결정합니다.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Uitgeschakeld",
|
||||
"disable": "Uitschakelen",
|
||||
"billing": "Abonnement",
|
||||
"here": "hier",
|
||||
"manage_your_billing_info": "Beheer uw betalingsgegevens en annuleer uw abonnement.",
|
||||
"availability": "Beschikbaarheid",
|
||||
"edit_availability": "Beschikbaarheid bewerken",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transcriptie van uw recente gesprek op {{appName}} is klaar om te downloaden. Links zijn slechts 1 uur geldig",
|
||||
"you_can_download_transcript_from_attachments": "Je kunt het transcript ook downloaden via de bijlagen",
|
||||
"link_valid_for_12_hrs": "Opmerking: De downloadlink is slechts 12 uur geldig. U kunt een nieuwe downloadlink genereren door de instructies <1>hier</1> te volgen.",
|
||||
"link_valid_for_12_hrs_description": "Opmerking: De downloadlink is slechts 12 uur geldig. Je kunt een nieuwe downloadlink genereren door de instructies te volgen.",
|
||||
"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.",
|
||||
"create_your_first_webhook": "Maak uw eerste webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Je doet een testboeking.",
|
||||
"icon_showcase": "Icoon overzicht",
|
||||
"icons_showcase": "Iconen overzicht",
|
||||
"migrating_from_team": "Migreren van team",
|
||||
"feature_currently_disabled": "Functie is momenteel uitgeschakeld",
|
||||
"choose_an_option": "Kies een optie",
|
||||
"enter_option_value": "Voer optiewaarde in",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Oplopend",
|
||||
"desc": "Aflopend",
|
||||
"verify_email_change": "Verifieer e-mailwijziging",
|
||||
"organization_slug_taken": "Organisatie-slug is al in gebruik",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Je kunt geen organisatie aanmaken omdat je al deel uitmaakt van een organisatie",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Je moet de gebruikers-onboarding voltooien voordat je een organisatie kunt aanmaken",
|
||||
"use_company_email_to_create_an_organization": "Gebruik een bedrijfse-mail om een organisatie aan te maken",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Je kunt geen platformorganisatie aanmaken omdat je al deel uitmaakt van een team",
|
||||
"you_need_to_have_minimum_published_teams": "Je moet minimaal gepubliceerde teams hebben",
|
||||
"you_are_part_of_this_organization_already": "Je maakt al deel uit van deze organisatie",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Je maakt deel uit van een andere organisatie, kan geen nieuwe organisatie aanmaken",
|
||||
"organization_payment_success": "Organisatiebetaling geslaagd",
|
||||
"organization_payment_success_description": "Je organisatie is succesvol aangemaakt",
|
||||
"this_may_take_a_few_seconds": "Dit kan een paar seconden duren...",
|
||||
"organization_onboarding_status": "Status organisatie-onboarding",
|
||||
"organization_onboarding_status_description": "Beschrijving status organisatie-onboarding",
|
||||
"payment_failed": "Betaling mislukt",
|
||||
"payment_failed_description": "Je betaling is mislukt. Probeer het opnieuw.",
|
||||
"creating_your_organization": "Je organisatie wordt aangemaakt",
|
||||
"organization_onboarding_already_completed": "Organisatie-onboarding al voltooid",
|
||||
"organization_onboarding_already_exists": "Organisatie-onboarding bestaat al",
|
||||
"organization_onboarding_not_found": "Organisatie-onboarding niet gevonden",
|
||||
"payment_successful": "Betaling geslaagd",
|
||||
"handover_onboarding_page_title": "Overdracht onboarding",
|
||||
"handover_onboarding_page_description": "Overdracht onboarding aan de gebruiker",
|
||||
"organization_already_exists_with_this_slug": "Er bestaat al een organisatie met deze slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Je hebt geen toestemming om een organisatie aan te maken voor dit e-mailadres",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Je hebt geen toestemming om een of meer teams te migreren",
|
||||
"organization_has_subscription_already": "De organisatie heeft al een abonnement",
|
||||
"rr_reset_interval": "Round Robin reset-interval",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Bepaalt hoe vaak de round robin boekingstelling wordt gereset om een evenwichtige verdeling te garanderen.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Deaktivert",
|
||||
"disable": "Deaktiver",
|
||||
"billing": "Betaling",
|
||||
"here": "her",
|
||||
"manage_your_billing_info": "Administrer betalingsinformasjonen din og kanseller abonnementet ditt.",
|
||||
"availability": "Tilgjengelighet",
|
||||
"edit_availability": "Rediger tilgjengelighet",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transkripsjon fra din nylige samtale på {{appName}} er klar for nedlasting. Lenker er kun gyldige i 1 time",
|
||||
"you_can_download_transcript_from_attachments": "Du kan også laste ned transkripsjonen fra vedleggene",
|
||||
"link_valid_for_12_hrs": "Merk: Nedlastingslenken er kun gyldig i 12 timer. Du kan generere en ny nedlastingslenke ved å følge instruksjonene <1>her</1>.",
|
||||
"link_valid_for_12_hrs_description": "Merk: Nedlastingslenken er kun gyldig i 12 timer. Du kan generere en ny nedlastingslenke ved å følge instruksjonene.",
|
||||
"create_your_first_form": "Lag ditt første skjema",
|
||||
"create_your_first_form_description": "Med Viderekoblings-skjema kan du stille kvalifiserende spørsmål og videresende til riktig person eller hendelsestype.",
|
||||
"create_your_first_webhook": "Lag din første Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Du gjør en testbestilling.",
|
||||
"icon_showcase": "Ikonvisning",
|
||||
"icons_showcase": "Ikonvisning",
|
||||
"migrating_from_team": "Migrerer fra team",
|
||||
"feature_currently_disabled": "Funksjonen er deaktivert",
|
||||
"choose_an_option": "Velg et alternativ",
|
||||
"enter_option_value": "Skriv inn alternativverdi",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Stigende",
|
||||
"desc": "Synkende",
|
||||
"verify_email_change": "Bekreft endring av e-post",
|
||||
"organization_slug_taken": "Organisasjonens kortnavn er allerede tatt",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Du kan ikke opprette en organisasjon fordi du allerede er en del av en organisasjon",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Du må fullføre brukeronboarding før du oppretter en organisasjon",
|
||||
"use_company_email_to_create_an_organization": "Bruk firmaets e-postadresse for å opprette en organisasjon",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Du kan ikke opprette en plattformorganisasjon fordi du allerede er en del av et team",
|
||||
"you_need_to_have_minimum_published_teams": "Du må ha et minimum antall publiserte team",
|
||||
"you_are_part_of_this_organization_already": "Du er allerede en del av denne organisasjonen",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Du er en del av en annen organisasjon, kan ikke opprette en ny organisasjon",
|
||||
"organization_payment_success": "Organisasjonsbetaling vellykket",
|
||||
"organization_payment_success_description": "Organisasjonen din har blitt opprettet",
|
||||
"this_may_take_a_few_seconds": "Dette kan ta noen sekunder...",
|
||||
"organization_onboarding_status": "Status for organisasjonsonboarding",
|
||||
"organization_onboarding_status_description": "Beskrivelse av status for organisasjonsonboarding",
|
||||
"payment_failed": "Betaling mislyktes",
|
||||
"payment_failed_description": "Betalingen din har mislyktes. Vennligst prøv igjen.",
|
||||
"creating_your_organization": "Oppretter organisasjonen din",
|
||||
"organization_onboarding_already_completed": "Organisasjonsonboarding er allerede fullført",
|
||||
"organization_onboarding_already_exists": "Organisasjonsonboarding eksisterer allerede",
|
||||
"organization_onboarding_not_found": "Organisasjonsonboarding ikke funnet",
|
||||
"payment_successful": "Betaling vellykket",
|
||||
"handover_onboarding_page_title": "Overføring av onboarding",
|
||||
"handover_onboarding_page_description": "Overføring av onboarding til brukeren",
|
||||
"organization_already_exists_with_this_slug": "En organisasjon med denne nettadressen eksisterer allerede",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Du har ikke tillatelse til å opprette en organisasjon for denne e-postadressen",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Du har ikke tillatelse til å migrere ett eller flere av teamene",
|
||||
"organization_has_subscription_already": "Organisasjonen har allerede et abonnement",
|
||||
"rr_reset_interval": "Round Robin tilbakestillingsintervall",
|
||||
"interval": "Intervall",
|
||||
"rr_reset_interval_description": "Bestemmer hvor ofte round robin-bookingtellingen tilbakestilles for å sikre balansert fordeling.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Wyłączone",
|
||||
"disable": "Wyłącz",
|
||||
"billing": "Rozliczenia",
|
||||
"here": "tutaj",
|
||||
"manage_your_billing_info": "Zarządzaj informacjami rozliczeniowymi i anuluj subskrypcję.",
|
||||
"availability": "Dostępność",
|
||||
"edit_availability": "Edytuj dostępność",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transkrypcja z Twojej ostatniej rozmowy na {{appName}} jest gotowa do pobrania. Linki są ważne tylko przez 1 godzinę",
|
||||
"you_can_download_transcript_from_attachments": "Możesz również pobrać transkrypcję z załączników",
|
||||
"link_valid_for_12_hrs": "Uwaga: Link do pobrania jest ważny tylko przez 12 godzin. Możesz wygenerować nowy link do pobrania, postępując zgodnie z instrukcjami <1>tutaj</1>.",
|
||||
"link_valid_for_12_hrs_description": "Uwaga: Link do pobrania jest ważny tylko przez 12 godzin. Możesz wygenerować nowy link do pobrania, postępując zgodnie z instrukcjami.",
|
||||
"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ń.",
|
||||
"create_your_first_webhook": "Utwórz pierwszy Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Wykonujesz testową rezerwację.",
|
||||
"icon_showcase": "Prezentacja ikon",
|
||||
"icons_showcase": "Prezentacja ikon",
|
||||
"migrating_from_team": "Migracja z zespołu",
|
||||
"feature_currently_disabled": "Funkcja jest obecnie wyłączona",
|
||||
"choose_an_option": "Wybierz opcję",
|
||||
"enter_option_value": "Wprowadź wartość opcji",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Rosnąco",
|
||||
"desc": "Malejąco",
|
||||
"verify_email_change": "Zweryfikuj zmianę adresu email",
|
||||
"organization_slug_taken": "Slug organizacji jest już zajęty",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Nie możesz utworzyć organizacji, ponieważ jesteś już częścią innej organizacji",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Musisz ukończyć proces wdrażania użytkownika przed utworzeniem organizacji",
|
||||
"use_company_email_to_create_an_organization": "Użyj służbowego adresu e-mail, aby utworzyć organizację",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Nie możesz utworzyć organizacji platformy, ponieważ jesteś już częścią zespołu",
|
||||
"you_need_to_have_minimum_published_teams": "Musisz mieć minimalną liczbę opublikowanych zespołów",
|
||||
"you_are_part_of_this_organization_already": "Jesteś już częścią tej organizacji",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Jesteś częścią innej organizacji, nie możesz utworzyć nowej organizacji",
|
||||
"organization_payment_success": "Płatność za organizację powiodła się",
|
||||
"organization_payment_success_description": "Twoja organizacja została pomyślnie utworzona",
|
||||
"this_may_take_a_few_seconds": "To może potrwać kilka sekund...",
|
||||
"organization_onboarding_status": "Status wdrażania organizacji",
|
||||
"organization_onboarding_status_description": "Opis statusu wdrażania organizacji",
|
||||
"payment_failed": "Płatność nie powiodła się",
|
||||
"payment_failed_description": "Twoja płatność nie powiodła się. Spróbuj ponownie.",
|
||||
"creating_your_organization": "Tworzenie twojej organizacji",
|
||||
"organization_onboarding_already_completed": "Wdrażanie organizacji zostało już zakończone",
|
||||
"organization_onboarding_already_exists": "Wdrażanie organizacji już istnieje",
|
||||
"organization_onboarding_not_found": "Nie znaleziono wdrażania organizacji",
|
||||
"payment_successful": "Płatność powiodła się",
|
||||
"handover_onboarding_page_title": "Przekazanie wdrażania",
|
||||
"handover_onboarding_page_description": "Przekazanie wdrażania użytkownikowi",
|
||||
"organization_already_exists_with_this_slug": "Organizacja z tym slugiem już istnieje",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nie masz uprawnień do utworzenia organizacji dla tego adresu e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nie masz uprawnień do migracji jednego lub więcej zespołów",
|
||||
"organization_has_subscription_already": "Organizacja ma już subskrypcję",
|
||||
"rr_reset_interval": "Interwał resetowania Round Robin",
|
||||
"interval": "Interwał",
|
||||
"rr_reset_interval_description": "Określa, jak często resetuje się licznik rezerwacji Round Robin, aby zapewnić zrównoważony rozkład.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Desativado",
|
||||
"disable": "Desativar",
|
||||
"billing": "Faturamento",
|
||||
"here": "aqui",
|
||||
"manage_your_billing_info": "Gerenciar as suas informações de faturamento e cancelar a sua assinatura.",
|
||||
"availability": "Disponibilidade",
|
||||
"edit_availability": "Editar disponibilidade",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "As transcrições da sua ligação recente no {{appName}} já estão prontas para serem baixadas. Os links são válidos por apenas 1 hora",
|
||||
"you_can_download_transcript_from_attachments": "Você também pode baixar a transcrição dos anexos",
|
||||
"link_valid_for_12_hrs": "Nota: O link para baixar só é válido por 12 horas. Você pode gerar um novo link para baixar seguindo as seguintes instruções <1>aqui</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: O link de download é válido apenas por 12 horas. Você pode gerar um novo link de download seguindo as instruções.",
|
||||
"create_your_first_form": "Criar seu primeiro formulário",
|
||||
"create_your_first_form_description": "Com os Formulários de roteamento, você pode fazer perguntas e encaminhar para a pessoa correta ou o tipo de evento.",
|
||||
"create_your_first_webhook": "Criar seu primeiro Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Você está fazendo um agendamento de teste.",
|
||||
"icon_showcase": "Mostruário de ícones",
|
||||
"icons_showcase": "Mostruário de ícones",
|
||||
"migrating_from_team": "Migrando da equipe",
|
||||
"feature_currently_disabled": "O recurso está desativado no momento",
|
||||
"choose_an_option": "Escolha uma opção",
|
||||
"enter_option_value": "Digite o valor da opção",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Crescente",
|
||||
"desc": "Decrescente",
|
||||
"verify_email_change": "Verificar alteração de e-mail",
|
||||
"organization_slug_taken": "O slug da organização já está em uso",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Você não pode criar uma organização, pois já faz parte de uma",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Você precisa concluir a integração do usuário antes de criar uma organização",
|
||||
"use_company_email_to_create_an_organization": "Use o e-mail da empresa para criar uma organização",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Você não pode criar uma organização de plataforma, pois já faz parte de uma equipe",
|
||||
"you_need_to_have_minimum_published_teams": "Você precisa ter um número mínimo de equipes publicadas",
|
||||
"you_are_part_of_this_organization_already": "Você já faz parte desta organização",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Você faz parte de outra organização, não é possível criar uma nova",
|
||||
"organization_payment_success": "Pagamento da organização bem-sucedido",
|
||||
"organization_payment_success_description": "Sua organização foi criada com sucesso",
|
||||
"this_may_take_a_few_seconds": "Isso pode levar alguns segundos...",
|
||||
"organization_onboarding_status": "Status de integração da organização",
|
||||
"organization_onboarding_status_description": "Descrição do status de integração da organização",
|
||||
"payment_failed": "Falha no pagamento",
|
||||
"payment_failed_description": "Seu pagamento falhou. Por favor, tente novamente.",
|
||||
"creating_your_organization": "Criando sua organização",
|
||||
"organization_onboarding_already_completed": "Integração da organização já concluída",
|
||||
"organization_onboarding_already_exists": "Integração da organização já existe",
|
||||
"organization_onboarding_not_found": "Integração da organização não encontrada",
|
||||
"payment_successful": "Pagamento bem-sucedido",
|
||||
"handover_onboarding_page_title": "Transferência de integração",
|
||||
"handover_onboarding_page_description": "Transferir integração para o usuário",
|
||||
"organization_already_exists_with_this_slug": "Já existe uma organização com este slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Você não tem permissão para criar uma organização para este e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Você não tem permissão para migrar uma ou mais das equipes",
|
||||
"organization_has_subscription_already": "A organização já possui uma assinatura",
|
||||
"rr_reset_interval": "Intervalo de reinício do Round Robin",
|
||||
"interval": "Intervalo",
|
||||
"rr_reset_interval_description": "Determina com que frequência a contagem de reservas do round robin é reiniciada para garantir uma distribuição equilibrada.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Desativado",
|
||||
"disable": "Desativar",
|
||||
"billing": "Facturação",
|
||||
"here": "aqui",
|
||||
"manage_your_billing_info": "Gerir as suas informações de faturação e cancele a sua assinatura.",
|
||||
"availability": "Disponibilidade",
|
||||
"edit_availability": "Editar disponibilidade",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "A transcrição da sua chamada recente em {{appName}} está pronta ser transferida. As ligações são válidas apenas durante 1 hora",
|
||||
"you_can_download_transcript_from_attachments": "Você também pode baixar a transcrição dos anexos",
|
||||
"link_valid_for_12_hrs": "Nota: A ligação de transferência é válida apenas durante 12 horas. Pode gerar uma nova ligação de transferência seguindo as instruções <1>aqui</1>.",
|
||||
"link_valid_for_12_hrs_description": "Nota: O link de download é válido apenas por 12 horas. Você pode gerar um novo link de download seguindo as instruções.",
|
||||
"create_your_first_form": "Crie o seu primeiro formulário",
|
||||
"create_your_first_form_description": "Com os Formulários de encaminhamento, pode fazer questões qualitativas e encaminhar para a pessoa ou o tipo de evento correto.",
|
||||
"create_your_first_webhook": "Crie o seu primeiro Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Você está fazendo uma reserva de teste.",
|
||||
"icon_showcase": "Mostruário de ícones",
|
||||
"icons_showcase": "Mostruário de ícones",
|
||||
"migrating_from_team": "Migrando da equipe",
|
||||
"feature_currently_disabled": "Recurso está atualmente desativado",
|
||||
"choose_an_option": "Escolha uma opção",
|
||||
"enter_option_value": "Digite o valor da opção",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Crescente",
|
||||
"desc": "Decrescente",
|
||||
"verify_email_change": "Verificar alteração de e-mail",
|
||||
"organization_slug_taken": "O slug da organização já está em uso",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Você não pode criar uma organização pois já faz parte de uma",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Você precisa completar a integração do usuário antes de criar uma organização",
|
||||
"use_company_email_to_create_an_organization": "Use o e-mail da empresa para criar uma organização",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Você não pode criar uma organização de plataforma pois já faz parte de uma equipe",
|
||||
"you_need_to_have_minimum_published_teams": "Você precisa ter um mínimo de equipes publicadas",
|
||||
"you_are_part_of_this_organization_already": "Você já faz parte desta organização",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Você faz parte de outra organização, não é possível criar uma nova",
|
||||
"organization_payment_success": "Pagamento da organização bem-sucedido",
|
||||
"organization_payment_success_description": "Sua organização foi criada com sucesso",
|
||||
"this_may_take_a_few_seconds": "Isso pode levar alguns segundos...",
|
||||
"organization_onboarding_status": "Status de integração da organização",
|
||||
"organization_onboarding_status_description": "Descrição do status de integração da organização",
|
||||
"payment_failed": "Falha no pagamento",
|
||||
"payment_failed_description": "Seu pagamento falhou. Por favor, tente novamente.",
|
||||
"creating_your_organization": "Criando sua organização",
|
||||
"organization_onboarding_already_completed": "Integração da organização já concluída",
|
||||
"organization_onboarding_already_exists": "Integração da organização já existe",
|
||||
"organization_onboarding_not_found": "Integração da organização não encontrada",
|
||||
"payment_successful": "Pagamento bem-sucedido",
|
||||
"handover_onboarding_page_title": "Transferência de integração",
|
||||
"handover_onboarding_page_description": "Transferir integração para o usuário",
|
||||
"organization_already_exists_with_this_slug": "Já existe uma organização com este slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Você não tem permissão para criar uma organização para este e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Você não tem permissão para migrar uma ou mais das equipes",
|
||||
"organization_has_subscription_already": "A organização já possui uma assinatura",
|
||||
"rr_reset_interval": "Intervalo de reinício do Round Robin",
|
||||
"interval": "Intervalo",
|
||||
"rr_reset_interval_description": "Determina com que frequência a contagem de reservas do round robin é reiniciada para garantir uma distribuição equilibrada.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Dezactivat",
|
||||
"disable": "Dezactivează",
|
||||
"billing": "Facturare",
|
||||
"here": "aici",
|
||||
"manage_your_billing_info": "Gestionați informațiile de facturare și anulați abonamentul.",
|
||||
"availability": "Disponibilitate",
|
||||
"edit_availability": "Modificați disponibilitatea",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transcrierea de la apelul recent pe {{appName}} este gata pentru descărcare. Linkurile sunt valabile doar pentru 1 oră",
|
||||
"you_can_download_transcript_from_attachments": "Puteți descărca transcrierea din atașamente",
|
||||
"link_valid_for_12_hrs": "Notă: Linkul de descărcare este valabil doar 12 ore. Puteți genera un nou link de descărcare urmând instrucțiunile <1>aici</1>.",
|
||||
"link_valid_for_12_hrs_description": "Notă: Link-ul de descărcare este valabil doar pentru 12 ore. Puteți genera un nou link de descărcare urmând instrucțiunile.",
|
||||
"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.",
|
||||
"create_your_first_webhook": "Creați primul dvs. webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Efectuați o rezervare de test.",
|
||||
"icon_showcase": "Prezentare pictograme",
|
||||
"icons_showcase": "Prezentare pictograme",
|
||||
"migrating_from_team": "Migrare de la echipă",
|
||||
"feature_currently_disabled": "Funcționalitatea este momentan dezactivată",
|
||||
"choose_an_option": "Alege o opțiune",
|
||||
"enter_option_value": "Introdu valoarea opțiunii",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Crescător",
|
||||
"desc": "Descrescător",
|
||||
"verify_email_change": "Verifică schimbarea adresei de email",
|
||||
"organization_slug_taken": "Slug-ul organizației este deja folosit",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Nu puteți crea o organizație deoarece faceți deja parte dintr-o organizație",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Trebuie să finalizați procesul de onboarding al utilizatorului înainte de a crea o organizație",
|
||||
"use_company_email_to_create_an_organization": "Folosiți adresa de email a companiei pentru a crea o organizație",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Nu puteți crea o organizație de platformă deoarece faceți deja parte dintr-o echipă",
|
||||
"you_need_to_have_minimum_published_teams": "Trebuie să aveți un număr minim de echipe publicate",
|
||||
"you_are_part_of_this_organization_already": "Faceți deja parte din această organizație",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Faceți parte dintr-o altă organizație, nu puteți crea o nouă organizație",
|
||||
"organization_payment_success": "Plata pentru organizație a fost efectuată cu succes",
|
||||
"organization_payment_success_description": "Organizația dumneavoastră a fost creată cu succes",
|
||||
"this_may_take_a_few_seconds": "Acest lucru poate dura câteva secunde...",
|
||||
"organization_onboarding_status": "Starea procesului de onboarding al organizației",
|
||||
"organization_onboarding_status_description": "Descrierea stării procesului de onboarding al organizației",
|
||||
"payment_failed": "Plata a eșuat",
|
||||
"payment_failed_description": "Plata dumneavoastră a eșuat. Vă rugăm să încercați din nou.",
|
||||
"creating_your_organization": "Se creează organizația dumneavoastră",
|
||||
"organization_onboarding_already_completed": "Procesul de onboarding al organizației a fost deja finalizat",
|
||||
"organization_onboarding_already_exists": "Procesul de onboarding al organizației există deja",
|
||||
"organization_onboarding_not_found": "Procesul de onboarding al organizației nu a fost găsit",
|
||||
"payment_successful": "Plata a fost efectuată cu succes",
|
||||
"handover_onboarding_page_title": "Predare proces de onboarding",
|
||||
"handover_onboarding_page_description": "Predarea procesului de onboarding către utilizator",
|
||||
"organization_already_exists_with_this_slug": "Există deja o organizație cu acest slug",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nu aveți permisiunea de a crea o organizație pentru acest email",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nu aveți permisiunea de a migra una sau mai multe dintre echipe",
|
||||
"organization_has_subscription_already": "Organizația are deja un abonament",
|
||||
"rr_reset_interval": "Interval de resetare Round Robin",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Determină cât de des se resetează numărul de rezervări round robin pentru a asigura o distribuție echilibrată.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Выключено",
|
||||
"disable": "Выключить",
|
||||
"billing": "Биллинг",
|
||||
"here": "здесь",
|
||||
"manage_your_billing_info": "Управление платежной информацией и отменой подписки.",
|
||||
"availability": "Доступность",
|
||||
"edit_availability": "Изменить информацию о доступности",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Транскрипт вашего недавнего звонка в {{appName}} готов к скачиванию. Ссылки действительны только 1 час",
|
||||
"you_can_download_transcript_from_attachments": "Вы также можете скачать расшифровку из вложений",
|
||||
"link_valid_for_12_hrs": "Примечание: Ссылка для скачивания действительна только 12 часов. Вы можете создать новую ссылку для скачивания, следуя инструкциям <1>здесь</1>.",
|
||||
"link_valid_for_12_hrs_description": "Примечание: Ссылка для скачивания действительна только в течение 12 часов. Вы можете сгенерировать новую ссылку для скачивания, следуя инструкциям.",
|
||||
"create_your_first_form": "Создайте первую форму",
|
||||
"create_your_first_form_description": "Формы маршрутизации позволяют задавать пользователям уточняющие вопросы, чтобы перенаправлять их к соответствующему лицу или типу события.",
|
||||
"create_your_first_webhook": "Создайте свой первый вебхук",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Вы выполняете тестовое бронирование.",
|
||||
"icon_showcase": "Витрина иконок",
|
||||
"icons_showcase": "Витрина иконок",
|
||||
"migrating_from_team": "Миграция из команды",
|
||||
"feature_currently_disabled": "Функция в данный момент отключена",
|
||||
"choose_an_option": "Выберите вариант",
|
||||
"enter_option_value": "Введите значение варианта",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "По возрастанию",
|
||||
"desc": "По убыванию",
|
||||
"verify_email_change": "Подтвердить изменение email",
|
||||
"organization_slug_taken": "Слаг организации уже занят",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Вы не можете создать организацию, так как уже являетесь частью организации",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Вам необходимо завершить адаптацию пользователя перед созданием организации",
|
||||
"use_company_email_to_create_an_organization": "Используйте корпоративную электронную почту для создания организации",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Вы не можете создать платформенную организацию, так как уже являетесь частью команды",
|
||||
"you_need_to_have_minimum_published_teams": "У вас должно быть минимальное количество опубликованных команд",
|
||||
"you_are_part_of_this_organization_already": "Вы уже являетесь частью этой организации",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Вы являетесь частью другой организации, невозможно создать новую организацию",
|
||||
"organization_payment_success": "Успешная оплата организации",
|
||||
"organization_payment_success_description": "Ваша организация успешно создана",
|
||||
"this_may_take_a_few_seconds": "Это может занять несколько секунд...",
|
||||
"organization_onboarding_status": "Статус адаптации организации",
|
||||
"organization_onboarding_status_description": "Описание статуса адаптации организации",
|
||||
"payment_failed": "Оплата не удалась",
|
||||
"payment_failed_description": "Ваш платеж не прошел. Пожалуйста, попробуйте еще раз.",
|
||||
"creating_your_organization": "Создание вашей организации",
|
||||
"organization_onboarding_already_completed": "Адаптация организации уже завершена",
|
||||
"organization_onboarding_already_exists": "Адаптация организации уже существует",
|
||||
"organization_onboarding_not_found": "Адаптация организации не найдена",
|
||||
"payment_successful": "Оплата успешна",
|
||||
"handover_onboarding_page_title": "Передача адаптации",
|
||||
"handover_onboarding_page_description": "Передача адаптации пользователю",
|
||||
"organization_already_exists_with_this_slug": "Организация с таким слагом уже существует",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "У вас нет разрешения на создание организации для этого email",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "У вас нет разрешения на миграцию одной или нескольких команд",
|
||||
"organization_has_subscription_already": "У организации уже есть подписка",
|
||||
"rr_reset_interval": "Интервал сброса очередности",
|
||||
"interval": "Интервал",
|
||||
"rr_reset_interval_description": "Определяет, как часто сбрасывается счетчик бронирований по очереди для обеспечения равномерного распределения.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Zakázané",
|
||||
"disable": "Zakázať",
|
||||
"billing": "Fakturácia",
|
||||
"here": "tu",
|
||||
"manage_your_billing_info": "Spravujte svoje fakturačné údaje a zrušte svoje predplatné.",
|
||||
"availability": "Dostupnosť",
|
||||
"edit_availability": "Upraviť dostupnosť",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Prepis z vášho nedávneho hovoru v {{appName}} je pripravený na stiahnutie. Odkazy sú platné len 1 hodinu",
|
||||
"you_can_download_transcript_from_attachments": "Prepis si môžete stiahnuť aj z príloh",
|
||||
"link_valid_for_12_hrs": "Poznámka: Odkaz na stiahnutie je platný len 12 hodín. Nový odkaz na stiahnutie môžete vygenerovať podľa pokynov <1>tu</1>.",
|
||||
"link_valid_for_12_hrs_description": "Poznámka: Odkaz na stiahnutie je platný len 12 hodín. Nový odkaz na stiahnutie môžete vygenerovať podľa pokynov.",
|
||||
"create_your_first_form": "Vytvorte svoj prvý formulár",
|
||||
"create_your_first_form_description": "S Routing Forms môžete klásť kvalifikačné otázky a smerovať na správnu osobu alebo typ udalosti.",
|
||||
"create_your_first_webhook": "Vytvorte svoj prvý webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Robíte testovaciu rezerváciu.",
|
||||
"icon_showcase": "Ukážka ikony",
|
||||
"icons_showcase": "Ukážka ikon",
|
||||
"migrating_from_team": "Migrácia z tímu",
|
||||
"feature_currently_disabled": "Funkcia je momentálne deaktivovaná",
|
||||
"choose_an_option": "Vyberte možnosť",
|
||||
"enter_option_value": "Zadajte hodnotu možnosti",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Vzostupne",
|
||||
"desc": "Zostupne",
|
||||
"verify_email_change": "Overiť zmenu e-mailu",
|
||||
"organization_slug_taken": "Slug organizácie je už obsadený",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Nemôžete vytvoriť organizáciu, pretože už ste súčasťou organizácie",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Pred vytvorením organizácie musíte dokončiť úvodné zaškolenie používateľa",
|
||||
"use_company_email_to_create_an_organization": "Na vytvorenie organizácie použite firemný e-mail",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Nemôžete vytvoriť platformovú organizáciu, pretože už ste súčasťou tímu",
|
||||
"you_need_to_have_minimum_published_teams": "Musíte mať minimálny počet publikovaných tímov",
|
||||
"you_are_part_of_this_organization_already": "Už ste súčasťou tejto organizácie",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Ste súčasťou inej organizácie, nemôžete vytvoriť novú organizáciu",
|
||||
"organization_payment_success": "Platba za organizáciu bola úspešná",
|
||||
"organization_payment_success_description": "Vaša organizácia bola úspešne vytvorená",
|
||||
"this_may_take_a_few_seconds": "Môže to trvať niekoľko sekúnd...",
|
||||
"organization_onboarding_status": "Stav úvodného zaškolenia organizácie",
|
||||
"organization_onboarding_status_description": "Popis stavu úvodného zaškolenia organizácie",
|
||||
"payment_failed": "Platba zlyhala",
|
||||
"payment_failed_description": "Vaša platba zlyhala. Skúste to prosím znova.",
|
||||
"creating_your_organization": "Vytváranie vašej organizácie",
|
||||
"organization_onboarding_already_completed": "Úvodné zaškolenie organizácie už bolo dokončené",
|
||||
"organization_onboarding_already_exists": "Úvodné zaškolenie organizácie už existuje",
|
||||
"organization_onboarding_not_found": "Úvodné zaškolenie organizácie nebolo nájdené",
|
||||
"payment_successful": "Platba bola úspešná",
|
||||
"handover_onboarding_page_title": "Odovzdanie úvodného zaškolenia",
|
||||
"handover_onboarding_page_description": "Odovzdanie úvodného zaškolenia používateľovi",
|
||||
"organization_already_exists_with_this_slug": "Organizácia s týmto identifikátorom už existuje",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nemáte oprávnenie vytvoriť organizáciu pre tento e-mail",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nemáte oprávnenie migrovať jeden alebo viac tímov",
|
||||
"organization_has_subscription_already": "Organizácia už má predplatné",
|
||||
"rr_reset_interval": "Interval resetovania Round Robin",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Určuje, ako často sa resetuje počet rezervácií v systéme round robin, aby sa zabezpečila vyvážená distribúcia.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Onemogućeno",
|
||||
"disable": "Onemogući",
|
||||
"billing": "Naplate",
|
||||
"here": "ovde",
|
||||
"manage_your_billing_info": "Upravljajte svojim informacijama za plaćanje i otkažite pretplatu.",
|
||||
"availability": "Dostupnost",
|
||||
"edit_availability": "Uredi dostupnost",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transkript sa vašeg nedavnog poziva na {{appName}} je spreman za preuzimanje. Linkovi su važeći samo 1 sat",
|
||||
"you_can_download_transcript_from_attachments": "Takođe možete preuzeti transkript iz priloga",
|
||||
"link_valid_for_12_hrs": "Napomena: Link za preuzimanje važi samo 12 sati. Možete generisati novi link za preuzimanje prateći uputstva <1>ovde</1>.",
|
||||
"link_valid_for_12_hrs_description": "Napomena: Link za preuzimanje važi samo 12 sati. Možete generisati novi link za preuzimanje prateći uputstva.",
|
||||
"create_your_first_form": "Kreirajte vaš prvi formular",
|
||||
"create_your_first_form_description": "Sa formularima za rutiranje možete postavljati kvalifikaciona pitanja i usmeravati ih do prave osobe ili tipa događaja.",
|
||||
"create_your_first_webhook": "Kreirajte vaš prvi Webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Pravite probnu rezervaciju.",
|
||||
"icon_showcase": "Prikaz ikonica",
|
||||
"icons_showcase": "Prikaz ikonica",
|
||||
"migrating_from_team": "Migracija iz tima",
|
||||
"feature_currently_disabled": "Funkcija je trenutno onemogućena",
|
||||
"choose_an_option": "Izaberite opciju",
|
||||
"enter_option_value": "Unesite vrednost opcije",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Rastuće",
|
||||
"desc": "Opadajuće",
|
||||
"verify_email_change": "Potvrdi promenu email adrese",
|
||||
"organization_slug_taken": "Slug organizacije je već zauzet",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Ne možete kreirati organizaciju jer ste već deo neke organizacije",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Morate završiti korisničko uvođenje pre kreiranja organizacije",
|
||||
"use_company_email_to_create_an_organization": "Koristite kompanijski email za kreiranje organizacije",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Ne možete kreirati platformsku organizaciju jer ste već deo tima",
|
||||
"you_need_to_have_minimum_published_teams": "Morate imati minimalan broj objavljenih timova",
|
||||
"you_are_part_of_this_organization_already": "Već ste deo ove organizacije",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Deo ste druge organizacije, ne možete kreirati novu organizaciju",
|
||||
"organization_payment_success": "Uspešno plaćanje organizacije",
|
||||
"organization_payment_success_description": "Vaša organizacija je uspešno kreirana",
|
||||
"this_may_take_a_few_seconds": "Ovo može potrajati nekoliko sekundi...",
|
||||
"organization_onboarding_status": "Status uvođenja organizacije",
|
||||
"organization_onboarding_status_description": "Opis statusa uvođenja organizacije",
|
||||
"payment_failed": "Plaćanje nije uspelo",
|
||||
"payment_failed_description": "Vaše plaćanje nije uspelo. Molimo pokušajte ponovo.",
|
||||
"creating_your_organization": "Kreiranje vaše organizacije",
|
||||
"organization_onboarding_already_completed": "Uvođenje organizacije je već završeno",
|
||||
"organization_onboarding_already_exists": "Uvođenje organizacije već postoji",
|
||||
"organization_onboarding_not_found": "Uvođenje organizacije nije pronađeno",
|
||||
"payment_successful": "Plaćanje uspešno",
|
||||
"handover_onboarding_page_title": "Predaja uvođenja",
|
||||
"handover_onboarding_page_description": "Predaja uvođenja korisniku",
|
||||
"organization_already_exists_with_this_slug": "Organizacija sa ovim slug-om već postoji",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Nemate dozvolu da kreirate organizaciju za ovu e-poštu",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Nemate dozvolu da migrirate jedan ili više timova",
|
||||
"organization_has_subscription_already": "Organizacija već ima pretplatu",
|
||||
"rr_reset_interval": "Interval resetovanja kružnog dodeljivanja",
|
||||
"interval": "Interval",
|
||||
"rr_reset_interval_description": "Određuje koliko često se resetuje brojač kružnog dodeljivanja kako bi se osigurala uravnotežena distribucija.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Inaktiverad",
|
||||
"disable": "Inaktivera",
|
||||
"billing": "Fakturering",
|
||||
"here": "här",
|
||||
"manage_your_billing_info": "Hantera din faktureringsinformation och avsluta din prenumeration.",
|
||||
"availability": "Tillgänglighet",
|
||||
"edit_availability": "Redigera tillgänglighet",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Transkript från ditt senaste samtal på {{appName}} är redo att laddas ner. Länkar är endast giltiga i 1 timme",
|
||||
"you_can_download_transcript_from_attachments": "Du kan också ladda ner transkriptionen från bilagorna",
|
||||
"link_valid_for_12_hrs": "Obs: Nedladdningslänken är endast giltig i 12 timmar. Du kan generera en ny nedladdningslänk genom att följa instruktionerna <1>här</1>.",
|
||||
"link_valid_for_12_hrs_description": "Obs: Nedladdningslänken är endast giltig i 12 timmar. Du kan generera en ny nedladdningslänk genom att följa instruktionerna.",
|
||||
"create_your_first_form": "Skapa ditt första formulär",
|
||||
"create_your_first_form_description": "Med omdirigeringsformulär kan du ställa kvalificerade frågor och dirigera till rätt person eller händelsetyp.",
|
||||
"create_your_first_webhook": "Skapa din första webhook",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Du gör en testbokning.",
|
||||
"icon_showcase": "Ikonvisning",
|
||||
"icons_showcase": "Ikonvisning",
|
||||
"migrating_from_team": "Migrerar från team",
|
||||
"feature_currently_disabled": "Funktionen är för närvarande inaktiverad",
|
||||
"choose_an_option": "Välj ett alternativ",
|
||||
"enter_option_value": "Ange alternativets värde",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Stigande",
|
||||
"desc": "Fallande",
|
||||
"verify_email_change": "Verifiera ändring av e-postadress",
|
||||
"organization_slug_taken": "Organisationens slug är redan tagen",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Du kan inte skapa en organisation eftersom du redan är en del av en organisation",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Du måste slutföra användarintroduktionen innan du skapar en organisation",
|
||||
"use_company_email_to_create_an_organization": "Använd företagsmail för att skapa en organisation",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Du kan inte skapa en plattformsorganisation eftersom du redan är en del av ett team",
|
||||
"you_need_to_have_minimum_published_teams": "Du måste ha ett minimum antal publicerade team",
|
||||
"you_are_part_of_this_organization_already": "Du är redan en del av denna organisation",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Du är en del av en annan organisation, kan inte skapa en ny organisation",
|
||||
"organization_payment_success": "Organisationsbetalning lyckades",
|
||||
"organization_payment_success_description": "Din organisation har skapats framgångsrikt",
|
||||
"this_may_take_a_few_seconds": "Detta kan ta några sekunder...",
|
||||
"organization_onboarding_status": "Status för organisationsintroduktion",
|
||||
"organization_onboarding_status_description": "Beskrivning av status för organisationsintroduktion",
|
||||
"payment_failed": "Betalningen misslyckades",
|
||||
"payment_failed_description": "Din betalning har misslyckats. Vänligen försök igen.",
|
||||
"creating_your_organization": "Skapar din organisation",
|
||||
"organization_onboarding_already_completed": "Organisationsintroduktionen är redan slutförd",
|
||||
"organization_onboarding_already_exists": "Organisationsintroduktionen finns redan",
|
||||
"organization_onboarding_not_found": "Organisationsintroduktionen hittades inte",
|
||||
"payment_successful": "Betalningen lyckades",
|
||||
"handover_onboarding_page_title": "Överlämning av introduktion",
|
||||
"handover_onboarding_page_description": "Överlämning av introduktion till användaren",
|
||||
"organization_already_exists_with_this_slug": "En organisation med denna slug finns redan",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Du har inte behörighet att skapa en organisation för denna e-postadress",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Du har inte behörighet att migrera ett eller flera av teamen",
|
||||
"organization_has_subscription_already": "Organisationen har redan en prenumeration",
|
||||
"rr_reset_interval": "Återställningsintervall för Round Robin",
|
||||
"interval": "Intervall",
|
||||
"rr_reset_interval_description": "Bestämmer hur ofta bokningsräknaren för Round Robin återställs för att säkerställa en balanserad fördelning.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Devre dışı bırakıldı",
|
||||
"disable": "Devre dışı",
|
||||
"billing": "Fatura",
|
||||
"here": "burada",
|
||||
"manage_your_billing_info": "Fatura bilgilerinizi yönetin ve aboneliğinizi iptal edin.",
|
||||
"availability": "Müsaitlik",
|
||||
"edit_availability": "Müsaitlik durumunu düzenle",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "{{appName}} üzerindeki son görüşmenizin transkripti indirilmeye hazır. Bağlantılar sadece 1 saat geçerlidir.",
|
||||
"you_can_download_transcript_from_attachments": "Transkripti eklerden de indirebilirsiniz",
|
||||
"link_valid_for_12_hrs": "Not: İndirme bağlantısı sadece 12 saat geçerlidir. Yeni bir indirme bağlantısı oluşturmak için <1>buradaki</1> talimatları izleyebilirsiniz.",
|
||||
"link_valid_for_12_hrs_description": "Not: İndirme bağlantısı yalnızca 12 saat geçerlidir. Talimatları izleyerek yeni bir indirme bağlantısı oluşturabilirsiniz.",
|
||||
"create_your_first_form": "İlk formunuzu oluşturun",
|
||||
"create_your_first_form_description": "Yönlendirme Formları ile yeterlik soruları sorabilir ve bunları doğru kişiye veya etkinlik türüne yönlendirebilirsiniz.",
|
||||
"create_your_first_webhook": "İlk Web kancanızı oluşturun",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Test rezervasyonu yapıyorsunuz.",
|
||||
"icon_showcase": "İkon vitrini",
|
||||
"icons_showcase": "İkonlar vitrini",
|
||||
"migrating_from_team": "Takımdan taşınıyor",
|
||||
"feature_currently_disabled": "Özellik şu anda devre dışı",
|
||||
"choose_an_option": "Bir seçenek belirleyin",
|
||||
"enter_option_value": "Seçenek değerini girin",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Artan",
|
||||
"desc": "Azalan",
|
||||
"verify_email_change": "E-posta değişikliğini doğrula",
|
||||
"organization_slug_taken": "Organizasyon kısa adı zaten alınmış",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Zaten bir organizasyonun parçası olduğunuz için yeni bir organizasyon oluşturamazsınız",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Bir organizasyon oluşturmadan önce kullanıcı oryantasyonunu tamamlamanız gerekiyor",
|
||||
"use_company_email_to_create_an_organization": "Bir organizasyon oluşturmak için şirket e-postasını kullanın",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Zaten bir takımın parçası olduğunuz için bir platform organizasyonu oluşturamazsınız",
|
||||
"you_need_to_have_minimum_published_teams": "Minimum sayıda yayınlanmış takıma sahip olmanız gerekiyor",
|
||||
"you_are_part_of_this_organization_already": "Zaten bu organizasyonun bir parçasısınız",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Başka bir organizasyonun parçasısınız, yeni bir organizasyon oluşturamazsınız",
|
||||
"organization_payment_success": "Organizasyon ödemesi başarılı",
|
||||
"organization_payment_success_description": "Organizasyonunuz başarıyla oluşturuldu",
|
||||
"this_may_take_a_few_seconds": "Bu birkaç saniye sürebilir...",
|
||||
"organization_onboarding_status": "Organizasyon oryantasyon durumu",
|
||||
"organization_onboarding_status_description": "Organizasyon oryantasyon durumu açıklaması",
|
||||
"payment_failed": "Ödeme başarısız oldu",
|
||||
"payment_failed_description": "Ödemeniz başarısız oldu. Lütfen tekrar deneyin.",
|
||||
"creating_your_organization": "Organizasyonunuz oluşturuluyor",
|
||||
"organization_onboarding_already_completed": "Organizasyon oryantasyonu zaten tamamlandı",
|
||||
"organization_onboarding_already_exists": "Organizasyon oryantasyonu zaten mevcut",
|
||||
"organization_onboarding_not_found": "Organizasyon oryantasyonu bulunamadı",
|
||||
"payment_successful": "Ödeme başarılı",
|
||||
"handover_onboarding_page_title": "Oryantasyon devri",
|
||||
"handover_onboarding_page_description": "Oryantasyonu kullanıcıya devret",
|
||||
"organization_already_exists_with_this_slug": "Bu kısa ad (slug) ile bir organizasyon zaten mevcut",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Bu e-posta için bir organizasyon oluşturma izniniz yok",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Bir veya daha fazla takımı taşıma izniniz yok",
|
||||
"organization_has_subscription_already": "Organizasyonun zaten bir aboneliği var",
|
||||
"rr_reset_interval": "Round Robin Sıfırlama Aralığı",
|
||||
"interval": "Aralık",
|
||||
"rr_reset_interval_description": "Round robin rezervasyon sayısının dengeli dağılımı sağlamak için ne sıklıkta sıfırlanacağını belirler.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Вимкнено",
|
||||
"disable": "Вимкнути",
|
||||
"billing": "Виставлення рахунків",
|
||||
"here": "тут",
|
||||
"manage_your_billing_info": "Керуйте своїми даними для виставлення рахунків і підписками.",
|
||||
"availability": "Доступність",
|
||||
"edit_availability": "Редагувати дані про доступність",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Транскрипт вашого недавнього дзвінка на {{appName}} готовий до завантаження. Посилання дійсні лише протягом 1 години",
|
||||
"you_can_download_transcript_from_attachments": "Ви також можете завантажити розшифровку з вкладень",
|
||||
"link_valid_for_12_hrs": "Примітка: Посилання для завантаження дійсне лише протягом 12 годин. Ви можете створити нове посилання для завантаження, дотримуючись інструкцій <1>тут</1>.",
|
||||
"link_valid_for_12_hrs_description": "Примітка: Посилання для завантаження дійсне лише протягом 12 годин. Ви можете згенерувати нове посилання для завантаження, дотримуючись інструкцій.",
|
||||
"create_your_first_form": "Створіть свою першу форму",
|
||||
"create_your_first_form_description": "Форми переспрямування дають змогу надавати уточнювальні запитання та переходити до відповідної особи або типу заходу.",
|
||||
"create_your_first_webhook": "Створіть свій перший вебгук",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Ви робите тестове бронювання.",
|
||||
"icon_showcase": "Галерея іконок",
|
||||
"icons_showcase": "Галерея іконок",
|
||||
"migrating_from_team": "Міграція з команди",
|
||||
"feature_currently_disabled": "Функцію наразі вимкнено",
|
||||
"choose_an_option": "Оберіть опцію",
|
||||
"enter_option_value": "Введіть значення опції",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "За зростанням",
|
||||
"desc": "За спаданням",
|
||||
"verify_email_change": "Підтвердити зміну електронної пошти",
|
||||
"organization_slug_taken": "Ідентифікатор організації вже зайнятий",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Ви не можете створити організацію, оскільки вже є частиною іншої організації",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Вам потрібно завершити ознайомлення користувача перед створенням організації",
|
||||
"use_company_email_to_create_an_organization": "Використовуйте корпоративну електронну пошту для створення організації",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Ви не можете створити платформну організацію, оскільки вже є частиною команди",
|
||||
"you_need_to_have_minimum_published_teams": "Вам потрібно мати мінімальну кількість опублікованих команд",
|
||||
"you_are_part_of_this_organization_already": "Ви вже є частиною цієї організації",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Ви є частиною іншої організації, неможливо створити нову організацію",
|
||||
"organization_payment_success": "Успішна оплата організації",
|
||||
"organization_payment_success_description": "Вашу організацію успішно створено",
|
||||
"this_may_take_a_few_seconds": "Це може зайняти кілька секунд...",
|
||||
"organization_onboarding_status": "Статус ознайомлення з організацією",
|
||||
"organization_onboarding_status_description": "Опис статусу ознайомлення з організацією",
|
||||
"payment_failed": "Оплата не вдалася",
|
||||
"payment_failed_description": "Ваша оплата не вдалася. Будь ласка, спробуйте ще раз.",
|
||||
"creating_your_organization": "Створення вашої організації",
|
||||
"organization_onboarding_already_completed": "Ознайомлення з організацією вже завершено",
|
||||
"organization_onboarding_already_exists": "Ознайомлення з організацією вже існує",
|
||||
"organization_onboarding_not_found": "Ознайомлення з організацією не знайдено",
|
||||
"payment_successful": "Оплата успішна",
|
||||
"handover_onboarding_page_title": "Передача ознайомлення",
|
||||
"handover_onboarding_page_description": "Передача ознайомлення користувачу",
|
||||
"organization_already_exists_with_this_slug": "Організація з таким слагом вже існує",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "У вас немає дозволу створити організацію для цієї електронної адреси",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "У вас немає дозволу на міграцію однієї або кількох команд",
|
||||
"organization_has_subscription_already": "Організація вже має підписку",
|
||||
"rr_reset_interval": "Інтервал скидання ротації",
|
||||
"interval": "Інтервал",
|
||||
"rr_reset_interval_description": "Визначає, як часто скидається лічильник бронювань ротації для забезпечення збалансованого розподілу.",
|
||||
|
||||
@@ -867,6 +867,7 @@
|
||||
"disabled": "Đã tắt",
|
||||
"disable": "Tắt",
|
||||
"billing": "Thanh toán",
|
||||
"here": "tại đây",
|
||||
"manage_your_billing_info": "Quản lý thông tin thanh toán của bạn và hủy đăng ký của bạn.",
|
||||
"availability": "Lịch khả dụng",
|
||||
"edit_availability": "Sửa tình trạng trống lịch",
|
||||
@@ -1548,6 +1549,7 @@
|
||||
"transcript_from_previous_call": "Bản chép lời từ cuộc gọi gần đây của bạn trên {{appName}} đã sẵn sàng để tải xuống. Liên kết chỉ có hiệu lực trong 1 giờ",
|
||||
"you_can_download_transcript_from_attachments": "Bạn cũng có thể tải bản ghi từ phần đính kèm",
|
||||
"link_valid_for_12_hrs": "Lưu ý: Liên kết tải xuống chỉ có hiệu lực trong 12 giờ. Bạn có thể tạo liên kết tải xuống mới bằng cách làm theo hướng dẫn <1>tại đây</1>.",
|
||||
"link_valid_for_12_hrs_description": "Lưu ý: Liên kết tải xuống chỉ có hiệu lực trong 12 giờ. Bạn có thể tạo liên kết tải xuống mới bằng cách làm theo hướng dẫn.",
|
||||
"create_your_first_form": "Tạo biểu mẫu đầu tiên",
|
||||
"create_your_first_form_description": "Với Biểu mẫu định hướng, bạn có thể hỏi một số câu sơ tuyển và định hướng đến đúng người hay đúng loại sự kiện.",
|
||||
"create_your_first_webhook": "Tạo Webhook đầu tiên",
|
||||
@@ -2917,6 +2919,7 @@
|
||||
"dry_run_mode_active": "Bạn đang thực hiện đặt lịch thử nghiệm.",
|
||||
"icon_showcase": "Trưng bày biểu tượng",
|
||||
"icons_showcase": "Trưng bày các biểu tượng",
|
||||
"migrating_from_team": "Chuyển từ nhóm",
|
||||
"feature_currently_disabled": "Tính năng hiện đang bị vô hiệu hóa",
|
||||
"choose_an_option": "Chọn một tùy chọn",
|
||||
"enter_option_value": "Nhập giá trị tùy chọn",
|
||||
@@ -2946,6 +2949,32 @@
|
||||
"asc": "Tăng dần",
|
||||
"desc": "Giảm dần",
|
||||
"verify_email_change": "Xác minh thay đổi email",
|
||||
"organization_slug_taken": "Slug của tổ chức đã được sử dụng",
|
||||
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "Bạn không thể tạo một tổ chức vì bạn đã là thành viên của một tổ chức khác",
|
||||
"you_need_to_complete_user_onboarding_before_creating_an_organization": "Bạn cần hoàn thành quá trình hướng dẫn người dùng trước khi tạo một tổ chức",
|
||||
"use_company_email_to_create_an_organization": "Sử dụng email công ty để tạo một tổ chức",
|
||||
"you_cannot_create_a_platform_organization_as_you_are_already_part_of_a_team": "Bạn không thể tạo một tổ chức nền tảng vì bạn đã là thành viên của một nhóm",
|
||||
"you_need_to_have_minimum_published_teams": "Bạn cần có số lượng nhóm đã xuất bản tối thiểu",
|
||||
"you_are_part_of_this_organization_already": "Bạn đã là thành viên của tổ chức này rồi",
|
||||
"you_are_part_of_another_organization_cannot_create_organization": "Bạn đã là thành viên của một tổ chức khác, không thể tạo tổ chức mới",
|
||||
"organization_payment_success": "Thanh toán tổ chức thành công",
|
||||
"organization_payment_success_description": "Tổ chức của bạn đã được tạo thành công",
|
||||
"this_may_take_a_few_seconds": "Điều này có thể mất vài giây...",
|
||||
"organization_onboarding_status": "Trạng thái hướng dẫn tổ chức",
|
||||
"organization_onboarding_status_description": "Mô tả trạng thái hướng dẫn tổ chức",
|
||||
"payment_failed": "Thanh toán thất bại",
|
||||
"payment_failed_description": "Thanh toán của bạn đã thất bại. Vui lòng thử lại.",
|
||||
"creating_your_organization": "Đang tạo tổ chức của bạn",
|
||||
"organization_onboarding_already_completed": "Quá trình hướng dẫn tổ chức đã hoàn thành",
|
||||
"organization_onboarding_already_exists": "Quá trình hướng dẫn tổ chức đã tồn tại",
|
||||
"organization_onboarding_not_found": "Không tìm thấy quá trình hướng dẫn tổ chức",
|
||||
"payment_successful": "Thanh toán thành công",
|
||||
"handover_onboarding_page_title": "Bàn giao hướng dẫn",
|
||||
"handover_onboarding_page_description": "Bàn giao quá trình hướng dẫn cho người dùng",
|
||||
"organization_already_exists_with_this_slug": "Tổ chức với slug này đã tồn tại",
|
||||
"you_do_not_have_permission_to_create_an_organization_for_this_email": "Bạn không có quyền tạo tổ chức cho email này",
|
||||
"you_do_not_have_permission_to_migrate_one_or_more_of_the_teams": "Bạn không có quyền di chuyển một hoặc nhiều nhóm",
|
||||
"organization_has_subscription_already": "Tổ chức đã có đăng ký",
|
||||
"rr_reset_interval": "Khoảng thời gian đặt lại Round Robin",
|
||||
"interval": "Khoảng thời gian",
|
||||
"rr_reset_interval_description": "Xác định tần suất đặt lại số lượng đặt lịch round robin để đảm bảo phân phối cân bằng.",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user