Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8f6c31e40 | ||
|
|
7246fa4084 | ||
|
|
039a0b7a85 | ||
|
|
12c5005305 | ||
|
|
1ff6465384 | ||
|
|
ae706bb6d6 | ||
|
|
538a39328e | ||
|
|
3589767099 | ||
|
|
ff2754f663 | ||
|
|
65484e7d01 | ||
|
|
4d942a454a | ||
|
|
7dbcb62724 | ||
|
|
c197c33fd0 | ||
|
|
815065d67c | ||
|
|
02cecd6707 | ||
|
|
81386d4ec0 | ||
|
|
204e411585 | ||
|
|
1ec1554cb5 | ||
|
|
241579eba6 | ||
|
|
8ccad29ab6 | ||
|
|
74b4d7a94a | ||
|
|
5c6e60b726 | ||
|
|
18c7c3c940 | ||
|
|
fbd113b976 | ||
|
|
c7f11c6795 | ||
|
|
84fb9bb371 | ||
|
|
1aac70f643 | ||
|
|
0dde8c1db9 | ||
|
|
0da3a9fa11 | ||
|
|
eb8f5bd194 | ||
|
|
82901fee94 | ||
|
|
4e0e3a47f5 | ||
|
|
dc400d80d0 | ||
|
|
6889592d4f | ||
|
|
95b833bc1c | ||
|
|
b06683458a | ||
|
|
01d764c6d3 | ||
|
|
49333addc2 | ||
|
|
6c40d29745 | ||
|
|
fc5ad53a6d | ||
|
|
4d38c6d0c7 | ||
|
|
cd15335eed | ||
|
|
aaa75100d4 | ||
|
|
ae9063804d | ||
|
|
30f9d9b980 | ||
|
|
42a264380a | ||
|
|
62aaba32cf | ||
|
|
aaf630f01f | ||
|
|
838e8b9e89 | ||
|
|
ce373c475c | ||
|
|
ed662b7956 | ||
|
|
2e49110ce6 | ||
|
|
fc35f9de85 | ||
|
|
9c67ee7375 | ||
|
|
a1477dc7e1 | ||
|
|
25d39b4273 | ||
|
|
4976e24e12 | ||
|
|
5ae6e1e983 |
@@ -81,7 +81,7 @@ describe("retrieveScopedAccessibleUsers tests", () => {
|
||||
where: { email: "member2-acme@example.com" },
|
||||
});
|
||||
|
||||
expect(accessibleUserIds.length).toBe(3);
|
||||
expect(accessibleUserIds.length).toBe(11);
|
||||
expect(accessibleUserIds).toContain(memberOneUser.id);
|
||||
expect(accessibleUserIds).toContain(memberTwoUser.id);
|
||||
expect(accessibleUserIds).toContain(adminUser.id);
|
||||
|
||||
@@ -28,3 +28,7 @@ API_KEY_PREFIX=cal_
|
||||
GET_LICENSE_KEY_URL="https://console.cal.com/api/license"
|
||||
IS_E2E=false
|
||||
DOCS_URL=
|
||||
|
||||
# Axiom logging
|
||||
AXIOM_DATASET=
|
||||
AXIOM_TOKEN=
|
||||
|
||||
@@ -19,16 +19,17 @@
|
||||
"test:watch": "yarn dev:build && jest --watch",
|
||||
"test:cov": "yarn dev:build && jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "yarn dev:build && NODE_OPTIONS='--max_old_space_size=8192' jest --ci --forceExit --config ./jest-e2e.json",
|
||||
"test:e2e": "yarn dev:build && NODE_OPTIONS='--max_old_space_size=8192 --experimental-vm-modules' jest --ci --forceExit --config ./jest-e2e.json",
|
||||
"test:e2e:watch": "yarn dev:build && jest --runInBand --detectOpenHandles --forceExit --config ./jest-e2e.json --watch",
|
||||
"prisma": "yarn workspace @calcom/prisma prisma",
|
||||
"generate-schemas": "yarn prisma generate && yarn prisma format",
|
||||
"copy-swagger-module": "ts-node -r tsconfig-paths/register swagger/copy-swagger-module.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.56",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.60",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
@@ -69,7 +70,8 @@
|
||||
"rxjs": "^7.8.1",
|
||||
"stripe": "^15.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
"winston": "^3.11.0",
|
||||
"winston": "^3.13.0",
|
||||
"winston-transport": "^4.7.0",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -56,6 +56,17 @@ export class BookingsRepository_2024_08_13 {
|
||||
});
|
||||
}
|
||||
|
||||
async getByUidWithUser(bookingUid: string) {
|
||||
return this.dbRead.prisma.booking.findUnique({
|
||||
where: {
|
||||
uid: bookingUid,
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getByIdWithAttendeesAndUserAndEvent(id: number) {
|
||||
return this.dbRead.prisma.booking.findUnique({
|
||||
where: {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { BookingUidGuard } from "@/ee/bookings/2024-08-13/guards/booking-uid.gua
|
||||
import { CancelBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/cancel-booking.output";
|
||||
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 { ReassignBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/reassign-booking.output";
|
||||
import { RescheduleBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/reschedule-booking.output";
|
||||
import { BookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/bookings.service";
|
||||
import { VERSION_2024_08_13_VALUE } from "@/lib/api-versions";
|
||||
@@ -9,6 +10,7 @@ import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator";
|
||||
import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator";
|
||||
import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { UserWithProfile } from "@/modules/users/users.repository";
|
||||
import {
|
||||
Controller,
|
||||
Post,
|
||||
@@ -46,12 +48,12 @@ import {
|
||||
CreateBookingInputPipe,
|
||||
CreateBookingInput,
|
||||
GetBookingsInput_2024_08_13,
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
ReassignToUserBookingInput_2024_08_13,
|
||||
MarkAbsentBookingInput_2024_08_13,
|
||||
CreateBookingInput_2024_08_13,
|
||||
CreateInstantBookingInput_2024_08_13,
|
||||
CreateRecurringBookingInput_2024_08_13,
|
||||
DeclineBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
|
||||
@Controller({
|
||||
@@ -227,4 +229,104 @@ export class BookingsController_2024_08_13 {
|
||||
data: booking,
|
||||
};
|
||||
}
|
||||
|
||||
@Post("/:bookingUid/reassign")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Permissions([BOOKING_WRITE])
|
||||
@UseGuards(ApiAuthGuard, BookingUidGuard)
|
||||
@ApiHeader({
|
||||
name: "Authorization",
|
||||
description:
|
||||
"value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
required: true,
|
||||
})
|
||||
@ApiOperation({ summary: "Automatically reassign booking to a new host" })
|
||||
async reassignBooking(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@GetUser() user: UserWithProfile
|
||||
): Promise<ReassignBookingOutput_2024_08_13> {
|
||||
const booking = await this.bookingsService.reassignBooking(bookingUid, user);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: booking,
|
||||
};
|
||||
}
|
||||
|
||||
@Post("/:bookingUid/reassign/:userId")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Permissions([BOOKING_WRITE])
|
||||
@UseGuards(ApiAuthGuard, BookingUidGuard)
|
||||
@ApiHeader({
|
||||
name: "Authorization",
|
||||
description:
|
||||
"value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
required: true,
|
||||
})
|
||||
@ApiOperation({ summary: "Reassign a booking to a specific user" })
|
||||
async reassignBookingToUser(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@Param("userId") userId: number,
|
||||
@GetUser("id") reassignedById: number,
|
||||
@Body() body: ReassignToUserBookingInput_2024_08_13
|
||||
): Promise<ReassignBookingOutput_2024_08_13> {
|
||||
const booking = await this.bookingsService.reassignBookingToUser(
|
||||
bookingUid,
|
||||
userId,
|
||||
reassignedById,
|
||||
body
|
||||
);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: booking,
|
||||
};
|
||||
}
|
||||
|
||||
@Post("/:bookingUid/confirm")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Permissions([BOOKING_WRITE])
|
||||
@UseGuards(ApiAuthGuard, BookingUidGuard)
|
||||
@ApiHeader({
|
||||
name: "Authorization",
|
||||
description:
|
||||
"value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
required: true,
|
||||
})
|
||||
@ApiOperation({ summary: "Confirm booking that requires a confirmation" })
|
||||
async confirmBooking(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@GetUser() user: UserWithProfile
|
||||
): Promise<GetBookingOutput_2024_08_13> {
|
||||
const booking = await this.bookingsService.confirmBooking(bookingUid, user);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: booking,
|
||||
};
|
||||
}
|
||||
|
||||
@Post("/:bookingUid/decline")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Permissions([BOOKING_WRITE])
|
||||
@UseGuards(ApiAuthGuard, BookingUidGuard)
|
||||
@ApiHeader({
|
||||
name: "Authorization",
|
||||
description:
|
||||
"value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
required: true,
|
||||
})
|
||||
@ApiOperation({ summary: "Decline booking that requires a confirmation" })
|
||||
async declineBooking(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@Body() body: DeclineBookingInput_2024_08_13,
|
||||
@GetUser() user: UserWithProfile
|
||||
): Promise<GetBookingOutput_2024_08_13> {
|
||||
const booking = await this.bookingsService.declineBooking(bookingUid, user, body.reason);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: booking,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { CreateBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/create-booking.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";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
|
||||
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import {
|
||||
AttendeeScheduledEmail,
|
||||
OrganizerScheduledEmail,
|
||||
AttendeeDeclinedEmail,
|
||||
} from "@calcom/platform-libraries";
|
||||
import { BookingOutput_2024_08_13, GetBookingOutput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { Booking, PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
jest.spyOn(AttendeeScheduledEmail.prototype as any, "getHtml").mockImplementation(async function () {
|
||||
return "<html><body>Mocked Email Content</body></html>";
|
||||
});
|
||||
|
||||
jest.spyOn(OrganizerScheduledEmail.prototype as any, "getHtml").mockImplementation(async function () {
|
||||
return "<html><body>Mocked Email Content</body></html>";
|
||||
});
|
||||
|
||||
jest.spyOn(AttendeeDeclinedEmail.prototype as any, "getHtml").mockImplementation(async function () {
|
||||
return "<html><body>Mocked Email Content</body></html>";
|
||||
});
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Bookings confirmation", () => {
|
||||
let app: INestApplication;
|
||||
let organization: Team;
|
||||
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
let bookingsRepositoryFixture: BookingsRepositoryFixture;
|
||||
let schedulesService: SchedulesService_2024_04_15;
|
||||
let eventTypesRepositoryFixture: EventTypesRepositoryFixture;
|
||||
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture;
|
||||
let oAuthClient: PlatformOAuthClient;
|
||||
let teamRepositoryFixture: TeamRepositoryFixture;
|
||||
|
||||
const userEmail = "bookings-controller-e2e@api.com";
|
||||
let user: User;
|
||||
|
||||
let eventTypeId: number;
|
||||
const eventTypeSlug = "peer-coding";
|
||||
|
||||
let createdBooking1: Booking;
|
||||
let createdBooking2: Booking;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
userEmail,
|
||||
Test.createTestingModule({
|
||||
imports: [AppModule, PrismaModule, UsersModule, SchedulesModule_2024_04_15],
|
||||
})
|
||||
)
|
||||
.overrideGuard(PermissionsGuard)
|
||||
.useValue({
|
||||
canActivate: () => true,
|
||||
})
|
||||
.compile();
|
||||
|
||||
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
|
||||
bookingsRepositoryFixture = new BookingsRepositoryFixture(moduleRef);
|
||||
eventTypesRepositoryFixture = new EventTypesRepositoryFixture(moduleRef);
|
||||
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(moduleRef);
|
||||
teamRepositoryFixture = new TeamRepositoryFixture(moduleRef);
|
||||
schedulesService = moduleRef.get<SchedulesService_2024_04_15>(SchedulesService_2024_04_15);
|
||||
|
||||
organization = await teamRepositoryFixture.create({ name: "organization bookings" });
|
||||
oAuthClient = await createOAuthClient(organization.id);
|
||||
|
||||
user = await userRepositoryFixture.create({
|
||||
email: userEmail,
|
||||
});
|
||||
|
||||
const userSchedule: CreateScheduleInput_2024_04_15 = {
|
||||
name: "working time",
|
||||
timeZone: "Europe/Rome",
|
||||
isDefault: true,
|
||||
};
|
||||
await schedulesService.createUserSchedule(user.id, userSchedule);
|
||||
const event = await eventTypesRepositoryFixture.create(
|
||||
{ title: "peer coding", slug: eventTypeSlug, length: 60 },
|
||||
user.id
|
||||
);
|
||||
eventTypeId = event.id;
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
async function createOAuthClient(organizationId: number) {
|
||||
const data = {
|
||||
logo: "logo-url",
|
||||
name: "name",
|
||||
redirectUris: ["http://localhost:5555"],
|
||||
permissions: 32,
|
||||
};
|
||||
const secret = "secret";
|
||||
|
||||
const client = await oauthClientRepositoryFixture.create(organizationId, data, secret);
|
||||
return client;
|
||||
}
|
||||
|
||||
it("should be defined", () => {
|
||||
expect(userRepositoryFixture).toBeDefined();
|
||||
expect(user).toBeDefined();
|
||||
});
|
||||
|
||||
it("should confirm a booking", async () => {
|
||||
const status = "PENDING";
|
||||
createdBooking1 = await bookingsRepositoryFixture.create({
|
||||
user: {
|
||||
connect: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
startTime: new Date(Date.UTC(2050, 0, 7, 13, 0, 0)),
|
||||
endTime: new Date(Date.UTC(2050, 0, 7, 14, 0, 0)),
|
||||
title: "peer coding",
|
||||
uid: "peer-coding-one",
|
||||
eventType: {
|
||||
connect: {
|
||||
id: eventTypeId,
|
||||
},
|
||||
},
|
||||
location: "via 10, rome, italy",
|
||||
customInputs: {},
|
||||
metadata: {},
|
||||
responses: {
|
||||
name: "Bob",
|
||||
email: "bob@gmail.com",
|
||||
},
|
||||
attendees: {
|
||||
create: {
|
||||
email: "bob@gmail.com",
|
||||
name: "Bob",
|
||||
locale: "it",
|
||||
timeZone: "Europe/Rome",
|
||||
},
|
||||
},
|
||||
status,
|
||||
});
|
||||
expect(createdBooking1.status).toEqual("PENDING");
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${createdBooking1.uid}/confirm`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: GetBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(data.status).toEqual("accepted");
|
||||
|
||||
const dbBooking = await bookingsRepositoryFixture.getByUid(data.uid);
|
||||
expect(dbBooking?.status).toEqual("ACCEPTED");
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibily recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should decline a booking", async () => {
|
||||
const status = "PENDING";
|
||||
createdBooking2 = await bookingsRepositoryFixture.create({
|
||||
user: {
|
||||
connect: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
startTime: new Date(Date.UTC(2050, 0, 7, 10, 0, 0)),
|
||||
endTime: new Date(Date.UTC(2050, 0, 7, 11, 0, 0)),
|
||||
title: "peer coding",
|
||||
uid: "peer-coding-two",
|
||||
eventType: {
|
||||
connect: {
|
||||
id: eventTypeId,
|
||||
},
|
||||
},
|
||||
location: "via 10, rome, italy",
|
||||
customInputs: {},
|
||||
metadata: {},
|
||||
responses: {
|
||||
name: "Bob",
|
||||
email: "bob@gmail.com",
|
||||
},
|
||||
attendees: {
|
||||
create: {
|
||||
email: "bob@gmail.com",
|
||||
name: "Bob",
|
||||
locale: "it",
|
||||
timeZone: "Europe/Rome",
|
||||
},
|
||||
},
|
||||
status,
|
||||
});
|
||||
expect(createdBooking2.status).toEqual("PENDING");
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${createdBooking2.uid}/decline`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: GetBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(data.status).toEqual("rejected");
|
||||
|
||||
const dbBooking = await bookingsRepositoryFixture.getByUid(data.uid);
|
||||
expect(dbBooking?.status).toEqual("REJECTED");
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibily recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await oauthClientRepositoryFixture.delete(oAuthClient.id);
|
||||
await teamRepositoryFixture.delete(organization.id);
|
||||
await userRepositoryFixture.deleteByEmail(user.email);
|
||||
await bookingsRepositoryFixture.deleteAllBookings(user.id, user.email);
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
function responseDataIsBooking(data: any): data is BookingOutput_2024_08_13 {
|
||||
return !Array.isArray(data) && typeof data === "object" && data && "id" in data;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,337 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { CreateBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/create-booking.output";
|
||||
import { ReassignBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/reassign-booking.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";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { Booking, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
import { HostsRepositoryFixture } from "test/fixtures/repository/hosts.repository.fixture";
|
||||
import { MembershipRepositoryFixture } from "test/fixtures/repository/membership.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
import { OrganizationRepositoryFixture } from "test/fixtures/repository/organization.repository.fixture";
|
||||
import { ProfileRepositoryFixture } from "test/fixtures/repository/profiles.repository.fixture";
|
||||
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
|
||||
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import {
|
||||
CreateBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
GetBookingsOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("Reassign bookings", () => {
|
||||
let app: INestApplication;
|
||||
let organization: Team;
|
||||
let team: Team;
|
||||
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
let bookingsRepositoryFixture: BookingsRepositoryFixture;
|
||||
let schedulesService: SchedulesService_2024_04_15;
|
||||
let eventTypesRepositoryFixture: EventTypesRepositoryFixture;
|
||||
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture;
|
||||
let oAuthClient: PlatformOAuthClient;
|
||||
let teamRepositoryFixture: TeamRepositoryFixture;
|
||||
let membershipsRepositoryFixture: MembershipRepositoryFixture;
|
||||
let hostsRepositoryFixture: HostsRepositoryFixture;
|
||||
let organizationsRepositoryFixture: OrganizationRepositoryFixture;
|
||||
let profileRepositoryFixture: ProfileRepositoryFixture;
|
||||
|
||||
const teamUserEmail = "orgUser1team1@api.com";
|
||||
const teamUserEmail2 = "orgUser2team1@api.com";
|
||||
let teamUser1: User;
|
||||
let teamUser2: User;
|
||||
|
||||
let teamRoundRobinEventTypeId: number;
|
||||
|
||||
let roundRobinBooking: Booking;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
teamUserEmail,
|
||||
Test.createTestingModule({
|
||||
imports: [AppModule, PrismaModule, UsersModule, SchedulesModule_2024_04_15],
|
||||
})
|
||||
)
|
||||
.overrideGuard(PermissionsGuard)
|
||||
.useValue({
|
||||
canActivate: () => true,
|
||||
})
|
||||
.compile();
|
||||
|
||||
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
|
||||
bookingsRepositoryFixture = new BookingsRepositoryFixture(moduleRef);
|
||||
eventTypesRepositoryFixture = new EventTypesRepositoryFixture(moduleRef);
|
||||
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(moduleRef);
|
||||
teamRepositoryFixture = new TeamRepositoryFixture(moduleRef);
|
||||
organizationsRepositoryFixture = new OrganizationRepositoryFixture(moduleRef);
|
||||
profileRepositoryFixture = new ProfileRepositoryFixture(moduleRef);
|
||||
membershipsRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
|
||||
hostsRepositoryFixture = new HostsRepositoryFixture(moduleRef);
|
||||
schedulesService = moduleRef.get<SchedulesService_2024_04_15>(SchedulesService_2024_04_15);
|
||||
|
||||
organization = await organizationsRepositoryFixture.create({ name: "organization team bookings" });
|
||||
team = await teamRepositoryFixture.create({
|
||||
name: "team 1",
|
||||
isOrganization: false,
|
||||
parent: { connect: { id: organization.id } },
|
||||
});
|
||||
|
||||
oAuthClient = await createOAuthClient(organization.id);
|
||||
|
||||
teamUser1 = await userRepositoryFixture.create({
|
||||
email: teamUserEmail,
|
||||
locale: "it",
|
||||
name: "orgUser1team1",
|
||||
});
|
||||
|
||||
teamUser2 = await userRepositoryFixture.create({
|
||||
email: teamUserEmail2,
|
||||
locale: "it",
|
||||
name: "orgUser2team1",
|
||||
});
|
||||
|
||||
const userSchedule: CreateScheduleInput_2024_04_15 = {
|
||||
name: "working time",
|
||||
timeZone: "Europe/Rome",
|
||||
isDefault: true,
|
||||
};
|
||||
await schedulesService.createUserSchedule(teamUser1.id, userSchedule);
|
||||
await schedulesService.createUserSchedule(teamUser2.id, userSchedule);
|
||||
|
||||
await profileRepositoryFixture.create({
|
||||
uid: `usr-${teamUser1.id}`,
|
||||
username: teamUserEmail,
|
||||
organization: {
|
||||
connect: {
|
||||
id: organization.id,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connect: {
|
||||
id: teamUser1.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await profileRepositoryFixture.create({
|
||||
uid: `usr-${teamUser2.id}`,
|
||||
username: teamUserEmail2,
|
||||
organization: {
|
||||
connect: {
|
||||
id: organization.id,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connect: {
|
||||
id: teamUser2.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await membershipsRepositoryFixture.create({
|
||||
role: "MEMBER",
|
||||
team: { connect: { id: team.id } },
|
||||
user: { connect: { id: teamUser1.id } },
|
||||
accepted: true,
|
||||
});
|
||||
|
||||
await membershipsRepositoryFixture.create({
|
||||
role: "MEMBER",
|
||||
team: { connect: { id: team.id } },
|
||||
user: { connect: { id: teamUser2.id } },
|
||||
accepted: true,
|
||||
});
|
||||
|
||||
const team1EventType = await eventTypesRepositoryFixture.createTeamEventType({
|
||||
schedulingType: "ROUND_ROBIN",
|
||||
team: {
|
||||
connect: { id: team.id },
|
||||
},
|
||||
users: {
|
||||
connect: [{ id: teamUser1.id }, { id: teamUser2.id }],
|
||||
},
|
||||
title: "Round Robin Event Type",
|
||||
slug: "round-robin-event-type",
|
||||
length: 60,
|
||||
assignAllTeamMembers: false,
|
||||
bookingFields: [],
|
||||
locations: [{ type: "inPerson", address: "via 10, rome, italy" }],
|
||||
});
|
||||
|
||||
teamRoundRobinEventTypeId = team1EventType.id;
|
||||
|
||||
await hostsRepositoryFixture.create({
|
||||
isFixed: false,
|
||||
user: {
|
||||
connect: {
|
||||
id: teamUser1.id,
|
||||
},
|
||||
},
|
||||
eventType: {
|
||||
connect: {
|
||||
id: team1EventType.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await hostsRepositoryFixture.create({
|
||||
isFixed: false,
|
||||
user: {
|
||||
connect: {
|
||||
id: teamUser2.id,
|
||||
},
|
||||
},
|
||||
eventType: {
|
||||
connect: {
|
||||
id: team1EventType.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
roundRobinBooking = await bookingsRepositoryFixture.create({
|
||||
user: {
|
||||
connect: {
|
||||
id: teamUser1.id,
|
||||
},
|
||||
},
|
||||
startTime: new Date(Date.UTC(2050, 0, 7, 13, 0, 0)),
|
||||
endTime: new Date(Date.UTC(2050, 0, 7, 14, 0, 0)),
|
||||
title: "round robin coding lets goo",
|
||||
uid: "round-robin-coding",
|
||||
eventType: {
|
||||
connect: {
|
||||
id: teamRoundRobinEventTypeId,
|
||||
},
|
||||
},
|
||||
location: "via 10, rome, italy",
|
||||
customInputs: {},
|
||||
metadata: {},
|
||||
responses: {
|
||||
name: "Bob",
|
||||
email: "bob@gmail.com",
|
||||
},
|
||||
attendees: {
|
||||
create: {
|
||||
email: "bob@gmail.com",
|
||||
name: "Bob",
|
||||
locale: "it",
|
||||
timeZone: "Europe/Rome",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it("should reassign round robin booking", async () => {
|
||||
const booking = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
expect(booking?.userId).toEqual(teamUser1.id);
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${roundRobinBooking.uid}/reassign`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: ReassignBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
|
||||
const data: ReassignBookingOutput_2024_08_13["data"] = responseBody.data;
|
||||
expect(data.bookingUid).toEqual(roundRobinBooking.uid);
|
||||
expect(data.reassignedTo).toEqual({
|
||||
id: teamUser2.id,
|
||||
name: teamUser2.name,
|
||||
email: teamUser2.email,
|
||||
});
|
||||
|
||||
const reassigned = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
expect(reassigned?.userId).toEqual(teamUser2.id);
|
||||
});
|
||||
});
|
||||
|
||||
it("should reassign round robin booking to a specific user", async () => {
|
||||
const booking = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
expect(booking?.userId).toEqual(teamUser2.id);
|
||||
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 8, 13, 0, 0)).toISOString(),
|
||||
eventTypeId: teamRoundRobinEventTypeId,
|
||||
attendee: {
|
||||
name: "alice",
|
||||
email: "alice@gmail.com",
|
||||
timeZone: "Europe/Madrid",
|
||||
language: "es",
|
||||
},
|
||||
meetingUrl: "https://meet.google.com/abc-def-ghi",
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${roundRobinBooking.uid}/reassign/${teamUser1.id}`)
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: ReassignBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
|
||||
const data: ReassignBookingOutput_2024_08_13["data"] = responseBody.data;
|
||||
expect(data.bookingUid).toEqual(roundRobinBooking.uid);
|
||||
expect(data.reassignedTo).toEqual({
|
||||
id: teamUser1.id,
|
||||
name: teamUser1.name,
|
||||
email: teamUser1.email,
|
||||
});
|
||||
|
||||
const reassigned = await bookingsRepositoryFixture.getByUid(roundRobinBooking.uid);
|
||||
expect(reassigned?.userId).toEqual(teamUser1.id);
|
||||
});
|
||||
});
|
||||
|
||||
async function createOAuthClient(organizationId: number) {
|
||||
const data = {
|
||||
logo: "logo-url",
|
||||
name: "name",
|
||||
redirectUris: ["http://localhost:5555"],
|
||||
permissions: 32,
|
||||
};
|
||||
const secret = "secret";
|
||||
|
||||
const client = await oauthClientRepositoryFixture.create(organizationId, data, secret);
|
||||
return client;
|
||||
}
|
||||
|
||||
function responseDataIsBooking(data: any): data is BookingOutput_2024_08_13 {
|
||||
return !Array.isArray(data) && typeof data === "object" && data && "id" in data;
|
||||
}
|
||||
|
||||
afterAll(async () => {
|
||||
await oauthClientRepositoryFixture.delete(oAuthClient.id);
|
||||
await teamRepositoryFixture.delete(organization.id);
|
||||
await userRepositoryFixture.deleteByEmail(teamUser1.email);
|
||||
await userRepositoryFixture.deleteByEmail(teamUserEmail2);
|
||||
await bookingsRepositoryFixture.deleteAllBookings(teamUser1.id, teamUser1.email);
|
||||
await bookingsRepositoryFixture.deleteAllBookings(teamUser2.id, teamUser2.email);
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { CancelBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/cancel-booking.output";
|
||||
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 { 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";
|
||||
import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { EventType, User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
|
||||
import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
|
||||
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { CAL_API_VERSION_HEADER, SUCCESS_STATUS, VERSION_2024_08_13 } from "@calcom/platform-constants";
|
||||
import { CreateBookingInput_2024_08_13, BookingOutput_2024_08_13 } from "@calcom/platform-types";
|
||||
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Bookings Endpoints 2024-08-13", () => {
|
||||
describe("User bookings", () => {
|
||||
let app: INestApplication;
|
||||
let organization: Team;
|
||||
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
let bookingsRepositoryFixture: BookingsRepositoryFixture;
|
||||
let schedulesService: SchedulesService_2024_04_15;
|
||||
let eventTypesRepositoryFixture: EventTypesRepositoryFixture;
|
||||
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture;
|
||||
let oAuthClient: PlatformOAuthClient;
|
||||
let teamRepositoryFixture: TeamRepositoryFixture;
|
||||
|
||||
const userEmail = "bookings-controller-e2e@api.com";
|
||||
let user: User;
|
||||
|
||||
let variableLengthEventType: EventType;
|
||||
const variableLengthEventTypeSlug = "variable-length-event";
|
||||
let normalEventType: EventType;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
userEmail,
|
||||
Test.createTestingModule({
|
||||
imports: [AppModule, PrismaModule, UsersModule, SchedulesModule_2024_04_15],
|
||||
})
|
||||
)
|
||||
.overrideGuard(PermissionsGuard)
|
||||
.useValue({
|
||||
canActivate: () => true,
|
||||
})
|
||||
.compile();
|
||||
|
||||
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
|
||||
bookingsRepositoryFixture = new BookingsRepositoryFixture(moduleRef);
|
||||
eventTypesRepositoryFixture = new EventTypesRepositoryFixture(moduleRef);
|
||||
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(moduleRef);
|
||||
teamRepositoryFixture = new TeamRepositoryFixture(moduleRef);
|
||||
schedulesService = moduleRef.get<SchedulesService_2024_04_15>(SchedulesService_2024_04_15);
|
||||
|
||||
organization = await teamRepositoryFixture.create({ name: "organization bookings" });
|
||||
oAuthClient = await createOAuthClient(organization.id);
|
||||
|
||||
user = await userRepositoryFixture.create({
|
||||
email: userEmail,
|
||||
});
|
||||
|
||||
const userSchedule: CreateScheduleInput_2024_04_15 = {
|
||||
name: "working time",
|
||||
timeZone: "Europe/Rome",
|
||||
isDefault: true,
|
||||
};
|
||||
await schedulesService.createUserSchedule(user.id, userSchedule);
|
||||
|
||||
variableLengthEventType = await eventTypesRepositoryFixture.create(
|
||||
{
|
||||
title: "variable length event",
|
||||
slug: variableLengthEventTypeSlug,
|
||||
length: 15,
|
||||
metadata: { multipleDuration: [15, 30, 60] },
|
||||
},
|
||||
user.id
|
||||
);
|
||||
|
||||
normalEventType = await eventTypesRepositoryFixture.create(
|
||||
{ title: "normal event", slug: "normal-event", length: 15 },
|
||||
user.id
|
||||
);
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
async function createOAuthClient(organizationId: number) {
|
||||
const data = {
|
||||
logo: "logo-url",
|
||||
name: "name",
|
||||
redirectUris: ["http://localhost:5555"],
|
||||
permissions: 32,
|
||||
};
|
||||
const secret = "secret";
|
||||
|
||||
const client = await oauthClientRepositoryFixture.create(organizationId, data, secret);
|
||||
return client;
|
||||
}
|
||||
|
||||
it("should be defined", () => {
|
||||
expect(userRepositoryFixture).toBeDefined();
|
||||
expect(user).toBeDefined();
|
||||
});
|
||||
|
||||
describe("create bookings", () => {
|
||||
it("should not be able to specify length of booking for non variable length event type", async () => {
|
||||
const lengthInMinutes = 30;
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 8, 10, 0, 0)).toISOString(),
|
||||
eventTypeId: normalEventType.id,
|
||||
lengthInMinutes,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
bookingFieldsResponses: {
|
||||
customField: "customValue",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it("should create a booking with default length", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2030, 0, 8, 10, 0, 0)).toISOString(),
|
||||
eventTypeId: variableLengthEventType.id,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
bookingFieldsResponses: {
|
||||
customField: "customValue",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(data.status).toEqual("accepted");
|
||||
expect(data.start).toEqual(body.start);
|
||||
expect(data.end).toEqual(
|
||||
new Date(Date.UTC(2030, 0, 8, 10, variableLengthEventType.length, 0)).toISOString()
|
||||
);
|
||||
expect(data.duration).toEqual(variableLengthEventType.length);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibily recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a booking with specified length that is not default length", async () => {
|
||||
const lengthInMinutes = 30;
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
lengthInMinutes,
|
||||
start: new Date(Date.UTC(2030, 0, 8, 11, 0, 0)).toISOString(),
|
||||
eventTypeId: variableLengthEventType.id,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
location: "https://meet.google.com/abc-def-ghi",
|
||||
bookingFieldsResponses: {
|
||||
customField: "customValue",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(data.status).toEqual("accepted");
|
||||
expect(data.start).toEqual(body.start);
|
||||
expect(data.end).toEqual(new Date(Date.UTC(2030, 0, 8, 11, lengthInMinutes, 0)).toISOString());
|
||||
expect(data.duration).toEqual(lengthInMinutes);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibily recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await oauthClientRepositoryFixture.delete(oAuthClient.id);
|
||||
await teamRepositoryFixture.delete(organization.id);
|
||||
await userRepositoryFixture.deleteByEmail(user.email);
|
||||
await bookingsRepositoryFixture.deleteAllBookings(user.id, user.email);
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
function responseDataIsBooking(data: any): data is BookingOutput_2024_08_13 {
|
||||
return !Array.isArray(data) && typeof data === "object" && data && "id" in data;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { ApiProperty, getSchemaPath } from "@nestjs/swagger";
|
||||
import { Type } from "class-transformer";
|
||||
import { IsEnum, ValidateNested } from "class-validator";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
|
||||
import { ReassignBookingOutput_2024_08_13 as ReassignBookingOutputData_2024_08_13 } from "@calcom/platform-types";
|
||||
|
||||
export class ReassignBookingOutput_2024_08_13 {
|
||||
@ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
|
||||
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
|
||||
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
|
||||
|
||||
@ApiProperty({
|
||||
oneOf: [{ $ref: getSchemaPath(ReassignBookingOutputData_2024_08_13) }],
|
||||
description:
|
||||
"Booking data, which can be either a ReassignAutoBookingOutput object or a ReassignManualBookingOutput object",
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => Object)
|
||||
data!: ReassignBookingOutputData_2024_08_13;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_20
|
||||
import { BillingService } from "@/modules/billing/services/billing.service";
|
||||
import { BookingSeatRepository } from "@/modules/booking-seat/booking-seat.repository";
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { UsersService } from "@/modules/users/services/users.service";
|
||||
import { UsersRepository, UserWithProfile } from "@/modules/users/users.repository";
|
||||
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { BadRequestException } from "@nestjs/common";
|
||||
import { Request } from "express";
|
||||
@@ -15,7 +17,10 @@ import {
|
||||
getAllUserBookings,
|
||||
handleInstantMeeting,
|
||||
handleCancelBooking,
|
||||
roundRobinReassignment,
|
||||
roundRobinManualReassignment,
|
||||
handleMarkNoShow,
|
||||
confirmBookingHandler,
|
||||
} from "@calcom/platform-libraries";
|
||||
import {
|
||||
CreateBookingInput_2024_08_13,
|
||||
@@ -23,8 +28,8 @@ import {
|
||||
CreateRecurringBookingInput_2024_08_13,
|
||||
GetBookingsInput_2024_08_13,
|
||||
CreateInstantBookingInput_2024_08_13,
|
||||
CancelBookingInput_2024_08_13,
|
||||
MarkAbsentBookingInput_2024_08_13,
|
||||
ReassignToUserBookingInput_2024_08_13,
|
||||
BookingOutput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
@@ -50,7 +55,9 @@ export class BookingsService_2024_08_13 {
|
||||
private readonly bookingSeatRepository: BookingSeatRepository,
|
||||
private readonly eventTypesRepository: EventTypesRepository_2024_06_14,
|
||||
private readonly prismaReadService: PrismaReadService,
|
||||
private readonly billingService: BillingService
|
||||
private readonly billingService: BillingService,
|
||||
private readonly usersService: UsersService,
|
||||
private readonly usersRepository: UsersRepository
|
||||
) {}
|
||||
|
||||
async createBooking(request: Request, body: CreateBookingInput) {
|
||||
@@ -358,4 +365,95 @@ export class BookingsService_2024_08_13 {
|
||||
fromReschedule: oldBookingUid,
|
||||
});
|
||||
}
|
||||
|
||||
async reassignBooking(bookingUid: string, requestUser: UserWithProfile) {
|
||||
const booking = await this.bookingsRepository.getByUid(bookingUid);
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
const profile = this.usersService.getUserMainProfile(requestUser);
|
||||
|
||||
await roundRobinReassignment({
|
||||
bookingId: booking.id,
|
||||
orgId: profile?.organizationId || null,
|
||||
});
|
||||
|
||||
const reassigned = await this.bookingsRepository.getByUidWithUser(bookingUid);
|
||||
if (!reassigned) {
|
||||
throw new NotFoundException(`Reassigned booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
return this.outputService.getOutputReassignedBooking(reassigned);
|
||||
}
|
||||
|
||||
async reassignBookingToUser(
|
||||
bookingUid: string,
|
||||
newUserId: number,
|
||||
reassignedById: number,
|
||||
body: ReassignToUserBookingInput_2024_08_13
|
||||
) {
|
||||
const booking = await this.bookingsRepository.getByUid(bookingUid);
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
const user = await this.usersRepository.findByIdWithProfile(newUserId);
|
||||
if (!user) {
|
||||
throw new NotFoundException(`User with id=${newUserId} was not found in the database`);
|
||||
}
|
||||
|
||||
const profile = this.usersService.getUserMainProfile(user);
|
||||
|
||||
const reassigned = await roundRobinManualReassignment({
|
||||
bookingId: booking.id,
|
||||
newUserId,
|
||||
orgId: profile?.organizationId || null,
|
||||
reassignReason: body.reason,
|
||||
reassignedById,
|
||||
});
|
||||
|
||||
return this.outputService.getOutputReassignedBooking(reassigned);
|
||||
}
|
||||
|
||||
async confirmBooking(bookingUid: string, requestUser: UserWithProfile) {
|
||||
const booking = await this.bookingsRepository.getByUid(bookingUid);
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
await confirmBookingHandler({
|
||||
ctx: {
|
||||
user: requestUser,
|
||||
},
|
||||
input: {
|
||||
bookingId: booking.id,
|
||||
confirmed: true,
|
||||
recurringEventId: booking.recurringEventId,
|
||||
},
|
||||
});
|
||||
|
||||
return this.getBooking(bookingUid);
|
||||
}
|
||||
|
||||
async declineBooking(bookingUid: string, requestUser: UserWithProfile, reason?: string) {
|
||||
const booking = await this.bookingsRepository.getByUid(bookingUid);
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
await confirmBookingHandler({
|
||||
ctx: {
|
||||
user: requestUser,
|
||||
},
|
||||
input: {
|
||||
bookingId: booking.id,
|
||||
confirmed: false,
|
||||
recurringEventId: booking.recurringEventId,
|
||||
reason,
|
||||
},
|
||||
});
|
||||
|
||||
return this.getBooking(bookingUid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import { z } from "zod";
|
||||
|
||||
import { X_CAL_CLIENT_ID } from "@calcom/platform-constants";
|
||||
import { EventTypeMetaDataSchema } from "@calcom/platform-libraries";
|
||||
import {
|
||||
CancelBookingInput,
|
||||
CancelBookingInput_2024_08_13,
|
||||
@@ -32,6 +33,7 @@ import {
|
||||
RescheduleBookingInput_2024_08_13,
|
||||
RescheduleSeatedBookingInput_2024_08_13,
|
||||
} from "@calcom/platform-types";
|
||||
import { EventType } from "@calcom/prisma/client";
|
||||
|
||||
type BookingRequest = NextApiRequest & { userId: number | undefined } & OAuthRequestParams;
|
||||
|
||||
@@ -123,10 +125,13 @@ export class InputBookingsService_2024_08_13 {
|
||||
throw new NotFoundException(`Event type with id=${inputBooking.eventTypeId} not found`);
|
||||
}
|
||||
|
||||
this.validateBookingLengthInMinutes(inputBooking, eventType);
|
||||
|
||||
const lengthInMinutes = inputBooking.lengthInMinutes ?? eventType.length;
|
||||
const startTime = DateTime.fromISO(inputBooking.start, { zone: "utc" }).setZone(
|
||||
inputBooking.attendee.timeZone
|
||||
);
|
||||
const endTime = startTime.plus({ minutes: eventType.length });
|
||||
const endTime = startTime.plus({ minutes: lengthInMinutes });
|
||||
|
||||
return {
|
||||
start: startTime.toISO(),
|
||||
@@ -150,6 +155,25 @@ export class InputBookingsService_2024_08_13 {
|
||||
};
|
||||
}
|
||||
|
||||
validateBookingLengthInMinutes(inputBooking: CreateBookingInput_2024_08_13, eventType: EventType) {
|
||||
const eventTypeMetadata = EventTypeMetaDataSchema.parse(eventType.metadata);
|
||||
if (inputBooking.lengthInMinutes && !eventTypeMetadata?.multipleDuration) {
|
||||
throw new BadRequestException(
|
||||
"Can't specify 'lengthInMinutes' because event type does not have multiple possible lengths. Please, remove the 'lengthInMinutes' field from the request."
|
||||
);
|
||||
}
|
||||
if (
|
||||
inputBooking.lengthInMinutes &&
|
||||
!eventTypeMetadata?.multipleDuration?.includes(inputBooking.lengthInMinutes)
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Provided 'lengthInMinutes' is not one of the possible lengths for the event type. The possible lengths are: ${eventTypeMetadata?.multipleDuration?.join(
|
||||
", "
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async createRecurringBookingRequest(
|
||||
request: Request,
|
||||
body: CreateRecurringBookingInput_2024_08_13
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
CreateSeatedBookingOutput_2024_08_13,
|
||||
GetRecurringSeatedBookingOutput_2024_08_13,
|
||||
GetSeatedBookingOutput_2024_08_13,
|
||||
ReassignBookingOutput_2024_08_13,
|
||||
RecurringBookingOutput_2024_08_13,
|
||||
SeatedAttendee,
|
||||
} from "@calcom/platform-types";
|
||||
@@ -50,6 +51,8 @@ type DatabaseBooking = Booking & {
|
||||
}[];
|
||||
} & { user: { id: number; name: string | null; email: string } | null };
|
||||
|
||||
type BookingWithUser = Booking & { user: { id: number; name: string | null; email: string } | null };
|
||||
|
||||
@Injectable()
|
||||
export class OutputBookingsService_2024_08_13 {
|
||||
constructor(private readonly bookingsRepository: BookingsRepository_2024_08_13) {}
|
||||
@@ -308,4 +311,17 @@ export class OutputBookingsService_2024_08_13 {
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
getOutputReassignedBooking(
|
||||
databaseBooking: Pick<BookingWithUser, "uid" | "user">
|
||||
): ReassignBookingOutput_2024_08_13 {
|
||||
return {
|
||||
bookingUid: databaseBooking.uid,
|
||||
reassignedTo: {
|
||||
id: databaseBooking?.user?.id || 0,
|
||||
name: databaseBooking?.user?.name || "unknown",
|
||||
email: databaseBooking?.user?.email || "unknown",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -212,6 +212,7 @@ describe("Event types Endpoints", () => {
|
||||
slug: "coding-class",
|
||||
description: "Let's learn how to code like a pro.",
|
||||
lengthInMinutes: 60,
|
||||
lengthInMinutesOptions: [30, 60, 90],
|
||||
locations: [
|
||||
{
|
||||
type: "integration",
|
||||
@@ -300,6 +301,7 @@ describe("Event types Endpoints", () => {
|
||||
expect(createdEventType.title).toEqual(body.title);
|
||||
expect(createdEventType.description).toEqual(body.description);
|
||||
expect(createdEventType.lengthInMinutes).toEqual(body.lengthInMinutes);
|
||||
expect(createdEventType.lengthInMinutesOptions).toEqual(body.lengthInMinutesOptions);
|
||||
expect(createdEventType.locations).toEqual(body.locations);
|
||||
expect(createdEventType.ownerId).toEqual(user.id);
|
||||
expect(createdEventType.scheduleId).toEqual(firstSchedule.id);
|
||||
@@ -360,6 +362,7 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType?.title).toEqual(eventType.title);
|
||||
expect(fetchedEventType?.description).toEqual(eventType.description);
|
||||
expect(fetchedEventType?.lengthInMinutes).toEqual(eventType.lengthInMinutes);
|
||||
expect(fetchedEventType?.lengthInMinutesOptions).toEqual(eventType.lengthInMinutesOptions);
|
||||
expect(fetchedEventType?.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType?.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType?.ownerId).toEqual(user.id);
|
||||
@@ -665,6 +668,7 @@ describe("Event types Endpoints", () => {
|
||||
const body: UpdateEventTypeInput_2024_06_14 = {
|
||||
title: newTitle,
|
||||
scheduleId: secondSchedule.id,
|
||||
lengthInMinutesOptions: [15, 30],
|
||||
bookingFields: [
|
||||
nameBookingField,
|
||||
{
|
||||
@@ -733,6 +737,7 @@ describe("Event types Endpoints", () => {
|
||||
|
||||
expect(updatedEventType.id).toEqual(eventType.id);
|
||||
expect(updatedEventType.title).toEqual(newTitle);
|
||||
expect(updatedEventType.lengthInMinutesOptions).toEqual(body.lengthInMinutesOptions);
|
||||
expect(updatedEventType.description).toEqual(eventType.description);
|
||||
expect(updatedEventType.lengthInMinutes).toEqual(eventType.lengthInMinutes);
|
||||
expect(updatedEventType.locations).toEqual(eventType.locations);
|
||||
@@ -772,6 +777,7 @@ describe("Event types Endpoints", () => {
|
||||
|
||||
eventType.title = newTitle;
|
||||
eventType.scheduleId = secondSchedule.id;
|
||||
eventType.lengthInMinutesOptions = updatedEventType.lengthInMinutesOptions;
|
||||
eventType.bookingLimitsCount = updatedEventType.bookingLimitsCount;
|
||||
eventType.onlyShowFirstAvailableSlot = updatedEventType.onlyShowFirstAvailableSlot;
|
||||
eventType.bookingLimitsDuration = updatedEventType.bookingLimitsDuration;
|
||||
@@ -819,6 +825,7 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType.title).toEqual(eventType.title);
|
||||
expect(fetchedEventType.description).toEqual(eventType.description);
|
||||
expect(fetchedEventType.lengthInMinutes).toEqual(eventType.lengthInMinutes);
|
||||
expect(fetchedEventType.lengthInMinutesOptions).toEqual(eventType.lengthInMinutesOptions);
|
||||
expect(fetchedEventType.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType.ownerId).toEqual(user.id);
|
||||
@@ -857,6 +864,7 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType?.title).toEqual(eventType.title);
|
||||
expect(fetchedEventType?.description).toEqual(eventType.description);
|
||||
expect(fetchedEventType?.lengthInMinutes).toEqual(eventType.lengthInMinutes);
|
||||
expect(fetchedEventType?.lengthInMinutesOptions).toEqual(eventType.lengthInMinutesOptions);
|
||||
expect(fetchedEventType?.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType?.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType?.ownerId).toEqual(user.id);
|
||||
|
||||
+4
@@ -104,6 +104,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
|
||||
const {
|
||||
lengthInMinutes,
|
||||
lengthInMinutesOptions,
|
||||
locations,
|
||||
bookingFields,
|
||||
bookingLimitsCount,
|
||||
@@ -135,6 +136,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
bookerLayouts: this.transformInputBookerLayouts(bookerLayouts),
|
||||
requiresConfirmationThreshold:
|
||||
confirmationPolicyTransformed?.requiresConfirmationThreshold ?? undefined,
|
||||
multipleDuration: lengthInMinutesOptions,
|
||||
},
|
||||
requiresConfirmation: confirmationPolicyTransformed?.requiresConfirmation ?? undefined,
|
||||
requiresConfirmationWillBlockSlot:
|
||||
@@ -152,6 +154,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
async transformInputUpdateEventType(inputEventType: UpdateEventTypeInput_2024_06_14, eventTypeId: number) {
|
||||
const {
|
||||
lengthInMinutes,
|
||||
lengthInMinutesOptions,
|
||||
locations,
|
||||
bookingFields,
|
||||
bookingLimitsCount,
|
||||
@@ -191,6 +194,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
bookerLayouts: this.transformInputBookerLayouts(bookerLayouts),
|
||||
requiresConfirmationThreshold:
|
||||
confirmationPolicyTransformed?.requiresConfirmationThreshold ?? undefined,
|
||||
multipleDuration: lengthInMinutesOptions,
|
||||
},
|
||||
recurringEvent: recurrence ? this.transformInputRecurrignEvent(recurrence) : undefined,
|
||||
requiresConfirmation: confirmationPolicyTransformed?.requiresConfirmation ?? undefined,
|
||||
|
||||
+1
@@ -153,6 +153,7 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
id,
|
||||
ownerId,
|
||||
lengthInMinutes: length,
|
||||
lengthInMinutesOptions: metadata.multipleDuration,
|
||||
title,
|
||||
slug,
|
||||
description: description || "",
|
||||
|
||||
@@ -28,6 +28,8 @@ export type Environment = {
|
||||
RATE_LIMIT_DEFAULT_LIMIT_ACCESS_TOKEN: number;
|
||||
RATE_LIMIT_DEFAULT_LIMIT: number;
|
||||
RATE_LIMIT_DEFAULT_BLOCK_DURATION_MS: number;
|
||||
AXIOM_DATASET: string;
|
||||
AXIOM_TOKEN: string;
|
||||
};
|
||||
|
||||
export const getEnv = <K extends keyof Environment>(key: K, fallback?: Environment[K]): Environment[K] => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { WinstonTransport as AxiomTransport } from "@axiomhq/winston";
|
||||
import type { LoggerOptions } from "winston";
|
||||
import { format, transports } from "winston";
|
||||
import { format, transports as Transports } from "winston";
|
||||
import type Transport from "winston-transport";
|
||||
|
||||
const formattedTimestamp = format.timestamp({
|
||||
format: "YYYY-MM-DD HH:mm:ss.SSS",
|
||||
@@ -36,13 +38,25 @@ export const logLevels = {
|
||||
export const loggerConfig = (): LoggerOptions => {
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
const transports: Transport[] = [];
|
||||
transports.push(new Transports.Console());
|
||||
|
||||
if (!!process.env.AXIOM_TOKEN && !!process.env.AXIOM_DATASET) {
|
||||
transports.push(
|
||||
new AxiomTransport({
|
||||
token: process.env.AXIOM_TOKEN,
|
||||
dataset: process.env.AXIOM_DATASET,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
levels: logLevels,
|
||||
level: process.env.LOG_LEVEL ?? "info",
|
||||
format: isProduction ? WINSTON_PROD_FORMAT : WINSTON_DEV_FORMAT,
|
||||
transports: [new transports.Console()],
|
||||
exceptionHandlers: [new transports.Console()],
|
||||
rejectionHandlers: [new transports.Console()],
|
||||
transports,
|
||||
exceptionHandlers: transports,
|
||||
rejectionHandlers: transports,
|
||||
defaultMeta: {
|
||||
service: "cal-platform-api",
|
||||
},
|
||||
|
||||
+12
-4
@@ -1,4 +1,5 @@
|
||||
import type { AppConfig } from "@/config/type";
|
||||
import { getEnv } from "@/env";
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
@@ -107,13 +108,20 @@ async function generateSwagger(app: NestExpressApplication<Server>) {
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
document.paths = groupAndSortPathsByFirstTag(document.paths);
|
||||
|
||||
const outputFile = "./swagger/documentation.json";
|
||||
const swaggerOutputFile = "./swagger/documentation.json";
|
||||
const docsOutputFile = "../../../docs/api-reference/v2/openapi.json";
|
||||
const stringifiedContents = JSON.stringify(document, null, 2);
|
||||
|
||||
if (fs.existsSync(outputFile)) {
|
||||
fs.unlinkSync(outputFile);
|
||||
if (fs.existsSync(swaggerOutputFile)) {
|
||||
fs.unlinkSync(swaggerOutputFile);
|
||||
}
|
||||
|
||||
fs.writeFileSync(outputFile, JSON.stringify(document, null, 2), { encoding: "utf8" });
|
||||
fs.writeFileSync(swaggerOutputFile, stringifiedContents, { encoding: "utf8" });
|
||||
|
||||
if (fs.existsSync(docsOutputFile) && getEnv("NODE_ENV") === "development") {
|
||||
fs.unlinkSync(docsOutputFile);
|
||||
fs.writeFileSync(docsOutputFile, stringifiedContents, { encoding: "utf8" });
|
||||
}
|
||||
|
||||
if (!process.env.DOCS_URL) {
|
||||
SwaggerModule.setup("docs", app, document, {
|
||||
|
||||
@@ -46,9 +46,9 @@ export class BillingProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
const stripeSubscription = await this.stripeService.stripe.subscriptions.retrieve(
|
||||
billingSubscription.subscriptionId
|
||||
);
|
||||
const stripeSubscription = await this.stripeService
|
||||
.getStripe()
|
||||
.subscriptions.retrieve(billingSubscription.subscriptionId);
|
||||
if (!stripeSubscription?.id) {
|
||||
this.logger.error(`Failed to retrieve stripe subscription (${billingSubscription.subscriptionId})`, {
|
||||
teamId,
|
||||
@@ -69,7 +69,7 @@ export class BillingProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.stripeService.stripe.subscriptionItems.createUsageRecord(meteredItem.id, {
|
||||
await this.stripeService.getStripe().subscriptionItems.createUsageRecord(meteredItem.id, {
|
||||
action: "increment",
|
||||
quantity: 1,
|
||||
timestamp: "now",
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { PlatformPlan } from "@/modules/billing/types";
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class BillingRepository {
|
||||
private readonly logger = new Logger("BillingRepository");
|
||||
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
|
||||
|
||||
getBillingForTeam = (teamId: number) =>
|
||||
@@ -30,6 +31,35 @@ export class BillingRepository {
|
||||
billingCycleEnd: billingEnd,
|
||||
subscriptionId,
|
||||
plan: plan.toString(),
|
||||
overdue: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async updateBillingOverdue(subId: string, cusId: string, overdue: boolean) {
|
||||
try {
|
||||
return this.dbWrite.prisma.platformBilling.update({
|
||||
where: {
|
||||
subscriptionId: subId,
|
||||
customerId: cusId,
|
||||
},
|
||||
data: {
|
||||
overdue,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.error("Could not update billing overdue", {
|
||||
subId,
|
||||
cusId,
|
||||
err,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async deleteBilling(id: number) {
|
||||
return this.dbWrite.prisma.platformBilling.delete({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { StripeService } from "@/modules/stripe/stripe.service";
|
||||
import { TokensModule } from "@/modules/tokens/tokens.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { UserWithProfile } from "@/modules/users/users.repository";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import Stripe from "stripe";
|
||||
import * as request from "supertest";
|
||||
import { PlatformBillingRepositoryFixture } from "test/fixtures/repository/billing.repository.fixture";
|
||||
import { MembershipRepositoryFixture } from "test/fixtures/repository/membership.repository.fixture";
|
||||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
|
||||
import { OrganizationRepositoryFixture } from "test/fixtures/repository/organization.repository.fixture";
|
||||
import { ProfileRepositoryFixture } from "test/fixtures/repository/profiles.repository.fixture";
|
||||
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { Team, PlatformOAuthClient, PlatformBilling } from "@calcom/prisma/client";
|
||||
|
||||
describe("Platform Billing Controller (e2e)", () => {
|
||||
let app: INestApplication;
|
||||
const userEmail = "platform-billing-controller-e2e@api.com";
|
||||
let user: UserWithProfile;
|
||||
let billing: PlatformBilling;
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
let organizationsRepositoryFixture: OrganizationRepositoryFixture;
|
||||
let profileRepositoryFixture: ProfileRepositoryFixture;
|
||||
let membershipsRepositoryFixture: MembershipRepositoryFixture;
|
||||
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture;
|
||||
let oAuthClient: PlatformOAuthClient;
|
||||
let platformBillingRepositoryFixture: PlatformBillingRepositoryFixture;
|
||||
let organization: Team;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
userEmail,
|
||||
Test.createTestingModule({
|
||||
imports: [AppModule, PrismaModule, UsersModule, TokensModule],
|
||||
})
|
||||
).compile();
|
||||
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
|
||||
organizationsRepositoryFixture = new OrganizationRepositoryFixture(moduleRef);
|
||||
profileRepositoryFixture = new ProfileRepositoryFixture(moduleRef);
|
||||
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(moduleRef);
|
||||
membershipsRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
|
||||
platformBillingRepositoryFixture = new PlatformBillingRepositoryFixture(moduleRef);
|
||||
organization = await organizationsRepositoryFixture.create({ name: "platform billing" });
|
||||
|
||||
user = await userRepositoryFixture.create({
|
||||
email: userEmail,
|
||||
username: userEmail,
|
||||
});
|
||||
|
||||
await profileRepositoryFixture.create({
|
||||
uid: `usr-${user.id}`,
|
||||
username: userEmail,
|
||||
organization: {
|
||||
connect: {
|
||||
id: organization.id,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
connect: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
await membershipsRepositoryFixture.create({
|
||||
role: "OWNER",
|
||||
team: { connect: { id: organization.id } },
|
||||
user: { connect: { id: user.id } },
|
||||
accepted: true,
|
||||
});
|
||||
|
||||
billing = await platformBillingRepositoryFixture.create(organization.id);
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
userRepositoryFixture.deleteByEmail(user.email);
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("/billing/webhook (POST) should set billing free plan for org", () => {
|
||||
jest.spyOn(StripeService.prototype, "getStripe").mockImplementation(
|
||||
() =>
|
||||
({
|
||||
webhooks: {
|
||||
constructEventAsync: async () => {
|
||||
return {
|
||||
type: "checkout.session.completed",
|
||||
data: {
|
||||
object: {
|
||||
metadata: {
|
||||
teamId: organization.id,
|
||||
plan: "FREE",
|
||||
},
|
||||
mode: "subscription",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
} as unknown as Stripe)
|
||||
);
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/billing/webhook")
|
||||
.expect(200)
|
||||
.then(async (res) => {
|
||||
const billing = await platformBillingRepositoryFixture.get(organization.id);
|
||||
expect(billing?.plan).toEqual("FREE");
|
||||
});
|
||||
});
|
||||
it("/billing/webhook (POST) failed payment should set billing free plan to overdue", () => {
|
||||
jest.spyOn(StripeService.prototype, "getStripe").mockImplementation(
|
||||
() =>
|
||||
({
|
||||
webhooks: {
|
||||
constructEventAsync: async () => {
|
||||
return {
|
||||
type: "invoice.payment_failed",
|
||||
data: {
|
||||
object: {
|
||||
customer: billing?.customerId,
|
||||
subscription: billing?.subscriptionId,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
} as unknown as Stripe)
|
||||
);
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/billing/webhook")
|
||||
.expect(200)
|
||||
.then(async (res) => {
|
||||
const billing = await platformBillingRepositoryFixture.get(organization.id);
|
||||
expect(billing?.overdue).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("/billing/webhook (POST) success payment should set billing free plan to not overdue", () => {
|
||||
jest.spyOn(StripeService.prototype, "getStripe").mockImplementation(
|
||||
() =>
|
||||
({
|
||||
webhooks: {
|
||||
constructEventAsync: async () => {
|
||||
return {
|
||||
type: "invoice.payment_succeeded",
|
||||
data: {
|
||||
object: {
|
||||
customer: billing?.customerId,
|
||||
subscription: billing?.subscriptionId,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
} as unknown as Stripe)
|
||||
);
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/billing/webhook")
|
||||
.expect(200)
|
||||
.then(async (res) => {
|
||||
const billing = await platformBillingRepositoryFixture.get(organization.id);
|
||||
expect(billing?.overdue).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it("/billing/webhook (POST) should delete subscription", () => {
|
||||
jest.spyOn(StripeService.prototype, "getStripe").mockImplementation(
|
||||
() =>
|
||||
({
|
||||
webhooks: {
|
||||
constructEventAsync: async () => {
|
||||
return {
|
||||
type: "customer.subscription.deleted",
|
||||
data: {
|
||||
object: {
|
||||
metadata: {
|
||||
teamId: organization.id,
|
||||
plan: "FREE",
|
||||
},
|
||||
id: billing?.subscriptionId,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
} as unknown as Stripe)
|
||||
);
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/billing/webhook")
|
||||
.expect(200)
|
||||
.then(async (res) => {
|
||||
const billing = await platformBillingRepositoryFixture.get(organization.id);
|
||||
expect(billing).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -102,13 +102,26 @@ export class BillingController {
|
||||
@Req() request: Request,
|
||||
@Headers("stripe-signature") stripeSignature: string
|
||||
): Promise<ApiResponse> {
|
||||
const event = await this.billingService.stripeService.stripe.webhooks.constructEventAsync(
|
||||
request.body,
|
||||
stripeSignature,
|
||||
this.stripeWhSecret
|
||||
);
|
||||
const event = await this.billingService.stripeService
|
||||
.getStripe()
|
||||
.webhooks.constructEventAsync(request.body, stripeSignature, this.stripeWhSecret);
|
||||
|
||||
await this.billingService.createOrUpdateStripeSubscription(event);
|
||||
switch (event.type) {
|
||||
case "checkout.session.completed":
|
||||
await this.billingService.handleStripeCheckoutEvents(event);
|
||||
break;
|
||||
case "customer.subscription.deleted":
|
||||
await this.billingService.handleStripeSubscriptionDeleted(event);
|
||||
break;
|
||||
case "invoice.payment_failed":
|
||||
await this.billingService.handleStripePaymentFailed(event);
|
||||
break;
|
||||
case "invoice.payment_succeeded":
|
||||
await this.billingService.handleStripePaymentSuccess(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
|
||||
@@ -64,7 +64,7 @@ export class BillingService implements OnModuleDestroy {
|
||||
}
|
||||
|
||||
async redirectToSubscribeCheckout(teamId: number, plan: PlatformPlan, customerId?: string) {
|
||||
const { url } = await this.stripeService.stripe.checkout.sessions.create({
|
||||
const { url } = await this.stripeService.getStripe().checkout.sessions.create({
|
||||
customer: customerId,
|
||||
line_items: [
|
||||
{
|
||||
@@ -101,7 +101,7 @@ export class BillingService implements OnModuleDestroy {
|
||||
const teamWithBilling = await this.teamsRepository.findByIdIncludeBilling(teamId);
|
||||
const customerId = teamWithBilling?.platformBilling?.customerId;
|
||||
|
||||
const { url } = await this.stripeService.stripe.checkout.sessions.create({
|
||||
const { url } = await this.stripeService.getStripe().checkout.sessions.create({
|
||||
customer: customerId,
|
||||
success_url: `${this.webAppUrl}/settings/platform/`,
|
||||
cancel_url: `${this.webAppUrl}/settings/platform/plans`,
|
||||
@@ -131,41 +131,92 @@ export class BillingService implements OnModuleDestroy {
|
||||
);
|
||||
}
|
||||
|
||||
async createOrUpdateStripeSubscription(event: Stripe.Event) {
|
||||
if (event.type === "checkout.session.completed") {
|
||||
const subscription = event.data.object as Stripe.Checkout.Session;
|
||||
|
||||
if (!subscription.metadata?.teamId) {
|
||||
return {
|
||||
status: "success",
|
||||
};
|
||||
}
|
||||
|
||||
const teamId = Number.parseInt(subscription.metadata.teamId);
|
||||
const plan = subscription.metadata.plan;
|
||||
if (!plan || !teamId) {
|
||||
this.logger.log("Webhook received but not pertaining to Platform, discarding.");
|
||||
return {
|
||||
status: "success",
|
||||
};
|
||||
}
|
||||
|
||||
if (subscription.mode === "subscription") {
|
||||
await this.setSubscriptionForTeam(
|
||||
async handleStripeSubscriptionDeleted(event: Stripe.Event) {
|
||||
const subscription = event.data.object as Stripe.Subscription;
|
||||
const teamId = subscription?.metadata?.teamId;
|
||||
const plan = PlatformPlan[subscription?.metadata?.plan?.toUpperCase() as keyof typeof PlatformPlan];
|
||||
if (teamId && plan) {
|
||||
const currentBilling = await this.billingRepository.getBillingForTeam(Number.parseInt(teamId));
|
||||
if (currentBilling?.subscriptionId === subscription.id) {
|
||||
await this.billingRepository.deleteBilling(currentBilling.id);
|
||||
this.logger.log(`Stripe Subscription deleted`, {
|
||||
customerId: currentBilling.customerId,
|
||||
subscriptionId: currentBilling.subscriptionId,
|
||||
teamId,
|
||||
subscription.subscription as string,
|
||||
PlatformPlan[plan.toUpperCase() as keyof typeof PlatformPlan]
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (subscription.mode === "setup") {
|
||||
await this.updateStripeSubscriptionForTeam(teamId, plan as PlatformPlan);
|
||||
}
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
};
|
||||
this.logger.log("No platform billing found.");
|
||||
return;
|
||||
}
|
||||
this.logger.log("Webhook received but not pertaining to Platform, discarding.");
|
||||
return;
|
||||
}
|
||||
|
||||
getSubscriptionIdFromInvoice(invoice: Stripe.Invoice): string | null {
|
||||
if (typeof invoice.subscription === "string") {
|
||||
return invoice.subscription;
|
||||
} else if (invoice.subscription && typeof invoice.subscription === "object") {
|
||||
return invoice.subscription.id;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
getCustomerIdFromInvoice(invoice: Stripe.Invoice): string | null {
|
||||
if (typeof invoice.customer === "string") {
|
||||
return invoice.customer;
|
||||
} else if (invoice.customer && typeof invoice.customer === "object") {
|
||||
return invoice.customer.id;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async handleStripePaymentSuccess(event: Stripe.Event) {
|
||||
const invoice = event.data.object as Stripe.Invoice;
|
||||
const subscriptionId = this.getSubscriptionIdFromInvoice(invoice);
|
||||
const customerId = this.getCustomerIdFromInvoice(invoice);
|
||||
if (subscriptionId && customerId) {
|
||||
await this.billingRepository.updateBillingOverdue(subscriptionId, customerId, false);
|
||||
}
|
||||
}
|
||||
|
||||
async handleStripePaymentFailed(event: Stripe.Event) {
|
||||
const invoice = event.data.object as Stripe.Invoice;
|
||||
const subscriptionId = this.getSubscriptionIdFromInvoice(invoice);
|
||||
const customerId = this.getCustomerIdFromInvoice(invoice);
|
||||
if (subscriptionId && customerId) {
|
||||
await this.billingRepository.updateBillingOverdue(subscriptionId, customerId, true);
|
||||
}
|
||||
}
|
||||
|
||||
async handleStripeCheckoutEvents(event: Stripe.Event) {
|
||||
const checkoutSession = event.data.object as Stripe.Checkout.Session;
|
||||
|
||||
if (!checkoutSession.metadata?.teamId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const teamId = Number.parseInt(checkoutSession.metadata.teamId);
|
||||
const plan = checkoutSession.metadata.plan;
|
||||
if (!plan || !teamId) {
|
||||
this.logger.log("Webhook received but not pertaining to Platform, discarding.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkoutSession.mode === "subscription") {
|
||||
await this.setSubscriptionForTeam(
|
||||
teamId,
|
||||
checkoutSession.subscription as string,
|
||||
PlatformPlan[plan.toUpperCase() as keyof typeof PlatformPlan]
|
||||
);
|
||||
}
|
||||
|
||||
if (checkoutSession.mode === "setup") {
|
||||
await this.updateStripeSubscriptionForTeam(teamId, plan as PlatformPlan);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async updateStripeSubscriptionForTeam(teamId: number, plan: PlatformPlan) {
|
||||
@@ -175,9 +226,9 @@ export class BillingService implements OnModuleDestroy {
|
||||
throw new NotFoundException("Team plan not found");
|
||||
}
|
||||
|
||||
const existingUserSubscription = await this.stripeService.stripe.subscriptions.retrieve(
|
||||
teamWithBilling?.platformBilling?.subscriptionId
|
||||
);
|
||||
const existingUserSubscription = await this.stripeService
|
||||
.getStripe()
|
||||
.subscriptions.retrieve(teamWithBilling?.platformBilling?.subscriptionId);
|
||||
const currentLicensedItem = existingUserSubscription.items.data.find(
|
||||
(item) => item.price?.recurring?.usage_type === "licensed"
|
||||
);
|
||||
@@ -193,21 +244,23 @@ export class BillingService implements OnModuleDestroy {
|
||||
throw new NotFoundException("There is no overage item present in the subscription");
|
||||
}
|
||||
|
||||
await this.stripeService.stripe.subscriptions.update(teamWithBilling?.platformBilling?.subscriptionId, {
|
||||
items: [
|
||||
{
|
||||
id: currentLicensedItem.id,
|
||||
price: this.billingConfigService.get(plan)?.base,
|
||||
},
|
||||
{
|
||||
id: currentOverageItem.id,
|
||||
price: this.billingConfigService.get(plan)?.overage,
|
||||
clear_usage: false,
|
||||
},
|
||||
],
|
||||
billing_cycle_anchor: "now",
|
||||
proration_behavior: "create_prorations",
|
||||
});
|
||||
await this.stripeService
|
||||
.getStripe()
|
||||
.subscriptions.update(teamWithBilling?.platformBilling?.subscriptionId, {
|
||||
items: [
|
||||
{
|
||||
id: currentLicensedItem.id,
|
||||
price: this.billingConfigService.get(plan)?.base,
|
||||
},
|
||||
{
|
||||
id: currentOverageItem.id,
|
||||
price: this.billingConfigService.get(plan)?.overage,
|
||||
clear_usage: false,
|
||||
},
|
||||
],
|
||||
billing_cycle_anchor: "now",
|
||||
proration_behavior: "create_prorations",
|
||||
});
|
||||
|
||||
await this.setSubscriptionForTeam(
|
||||
teamId,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export enum PlatformPlan {
|
||||
FREE = "FREE",
|
||||
STARTER = "STARTER",
|
||||
ESSENTIALS = "ESSENTIALS",
|
||||
SCALE = "SCALE",
|
||||
ENTERPRISE = "ENTERPRISE",
|
||||
}
|
||||
|
||||
export type PlatformPlanType = "STARTER" | "ESSENTIALS" | "SCALE" | "ENTERPRISE";
|
||||
export type PlatformPlanType = "FREE" | "STARTER" | "ESSENTIALS" | "SCALE" | "ENTERPRISE";
|
||||
|
||||
+3
-29
@@ -25,9 +25,9 @@ import {
|
||||
import {
|
||||
ApiTags as DocsTags,
|
||||
ApiExcludeController as DocsExcludeController,
|
||||
ApiExcludeEndpoint as DocsExcludeEndpoint,
|
||||
ApiOperation as DocsOperation,
|
||||
ApiOkResponse as DocsOkResponse,
|
||||
ApiExcludeEndpoint as DocsExcludeEndpoint,
|
||||
ApiBadRequestResponse as DocsBadRequestResponse,
|
||||
ApiHeader as DocsHeader,
|
||||
} from "@nestjs/swagger";
|
||||
@@ -50,20 +50,7 @@ export class OAuthFlowController {
|
||||
@Post("/authorize")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(NextAuthGuard)
|
||||
@DocsOperation({
|
||||
summary: "Authorize an OAuth client",
|
||||
description:
|
||||
"Redirects the user to the specified 'redirect_uri' with an authorization code in query parameter if the client is authorized successfully. The code is then exchanged for access and refresh tokens via the `/exchange` endpoint.",
|
||||
})
|
||||
@DocsOkResponse({
|
||||
description:
|
||||
"The user is redirected to the 'redirect_uri' with an authorization code in query parameter e.g. `redirectUri?code=secretcode.`",
|
||||
})
|
||||
@DocsBadRequestResponse({
|
||||
description:
|
||||
"Bad request if the OAuth client is not found, if the redirect URI is invalid, or if the user has already authorized the client.",
|
||||
})
|
||||
@DocsExcludeEndpoint(getEnv("NODE_ENV") === "production")
|
||||
@DocsExcludeEndpoint()
|
||||
async authorize(
|
||||
@Param("clientId") clientId: string,
|
||||
@Body() body: OAuthAuthorizeInput,
|
||||
@@ -97,20 +84,7 @@ export class OAuthFlowController {
|
||||
|
||||
@Post("/exchange")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@DocsOperation({
|
||||
summary: "Exchange authorization code for access tokens",
|
||||
description:
|
||||
"Exchanges the authorization code received from the `/authorize` endpoint for access and refresh tokens. The authorization code should be provided in the 'Authorization' header prefixed with 'Bearer '.",
|
||||
})
|
||||
@DocsOkResponse({
|
||||
type: KeysResponseDto,
|
||||
description: "Successfully exchanged authorization code for access and refresh tokens.",
|
||||
})
|
||||
@DocsBadRequestResponse({
|
||||
description:
|
||||
"Bad request if the authorization code is missing, invalid, or if the client ID and secret do not match.",
|
||||
})
|
||||
@DocsExcludeEndpoint(getEnv("NODE_ENV") === "production")
|
||||
@DocsExcludeEndpoint()
|
||||
async exchange(
|
||||
@Headers("Authorization") authorization: string,
|
||||
@Param("clientId") clientId: string,
|
||||
|
||||
+13
-2
@@ -31,6 +31,7 @@ import {
|
||||
HttpStatus,
|
||||
HttpCode,
|
||||
UnprocessableEntityException,
|
||||
Logger,
|
||||
} from "@nestjs/common";
|
||||
import { ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
import { plainToClass } from "class-transformer";
|
||||
@@ -46,6 +47,8 @@ import { SkipTakePagination } from "@calcom/platform-types";
|
||||
@UseGuards(ApiAuthGuard, IsOrgGuard, RolesGuard, IsTeamInOrg, PlatformPlanGuard, IsAdminAPIEnabledGuard)
|
||||
@DocsTags("Orgs / Teams / Memberships")
|
||||
export class OrganizationsTeamsMembershipsController {
|
||||
private logger = new Logger("OrganizationsTeamsMembershipsController");
|
||||
|
||||
constructor(
|
||||
private organizationsTeamsMembershipsService: OrganizationsTeamsMembershipsService,
|
||||
private oganizationsEventTypesService: OrganizationsEventTypesService,
|
||||
@@ -148,7 +151,11 @@ export class OrganizationsTeamsMembershipsController {
|
||||
);
|
||||
|
||||
if (!currentMembership.accepted && updatedMembership.accepted) {
|
||||
await updateNewTeamMemberEventTypes(updatedMembership.userId, teamId);
|
||||
try {
|
||||
await updateNewTeamMemberEventTypes(updatedMembership.userId, teamId);
|
||||
} catch (err) {
|
||||
this.logger.error("Could not update new team member eventTypes", err);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -175,7 +182,11 @@ export class OrganizationsTeamsMembershipsController {
|
||||
|
||||
const membership = await this.organizationsTeamsMembershipsService.createOrgTeamMembership(teamId, data);
|
||||
if (membership.accepted) {
|
||||
await updateNewTeamMemberEventTypes(user.id, teamId);
|
||||
try {
|
||||
await updateNewTeamMemberEventTypes(user.id, teamId);
|
||||
} catch (err) {
|
||||
this.logger.error("Could not update new team member eventTypes", err);
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
|
||||
@@ -33,7 +33,7 @@ export class OrganizationsRepository {
|
||||
}
|
||||
|
||||
async createNewBillingRelation(orgId: number, plan?: PlatformPlan) {
|
||||
const { id } = await this.stripeService.stripe.customers.create({
|
||||
const { id } = await this.stripeService.getStripe().customers.create({
|
||||
metadata: {
|
||||
createdBy: "oauth_client_no_csid", // mark in case this is needed in the future.
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ type IntegrationOAuthCallbackState = {
|
||||
|
||||
@Injectable()
|
||||
export class StripeService {
|
||||
public stripe: Stripe;
|
||||
private stripe: Stripe;
|
||||
private redirectUri = `${this.config.get("api.url")}/stripe/save`;
|
||||
|
||||
constructor(
|
||||
@@ -44,6 +44,10 @@ export class StripeService {
|
||||
});
|
||||
}
|
||||
|
||||
getStripe() {
|
||||
return this.stripe;
|
||||
}
|
||||
|
||||
async getStripeRedirectUrl(state: string, userEmail?: string, userName?: string | null) {
|
||||
const { client_id } = await this.getStripeAppKeys();
|
||||
|
||||
|
||||
@@ -82,7 +82,10 @@ export class WebhooksController {
|
||||
}
|
||||
|
||||
@Get("/")
|
||||
@ApiOperation({ summary: "Get all webooks (paginated)" })
|
||||
@ApiOperation({
|
||||
summary: "Get all webooks",
|
||||
description: "Gets a paginated list of webhooks for the authenticated user.",
|
||||
})
|
||||
async getWebhooks(
|
||||
@GetUser() user: UserWithProfile,
|
||||
@Query() query: SkipTakePagination
|
||||
|
||||
@@ -3257,6 +3257,230 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/bookings/{bookingUid}/reassign": {
|
||||
"post": {
|
||||
"operationId": "BookingsController_2024_08_13_reassignBooking",
|
||||
"summary": "Automatically reassign booking to a new host",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bookingUid",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Bookings"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/bookings/{bookingUid}/reassign/{userId}": {
|
||||
"post": {
|
||||
"operationId": "BookingsController_2024_08_13_reassignBookingToUser",
|
||||
"summary": "Reassign a booking to a specific user",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bookingUid",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "userId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ReassignToUserBookingInput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Bookings"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/bookings/{bookingUid}/confirm": {
|
||||
"post": {
|
||||
"operationId": "BookingsController_2024_08_13_confirmBooking",
|
||||
"summary": "Confirm booking that requires a confirmation",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bookingUid",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GetBookingOutput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Bookings"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/bookings/{bookingUid}/decline": {
|
||||
"post": {
|
||||
"operationId": "BookingsController_2024_08_13_declineBooking",
|
||||
"summary": "Decline booking that requires a confirmation",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
"in": "header",
|
||||
"description": "Must be set to `2024-08-13`",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bookingUid",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "value must be `Bearer <token>` where `<token>` either managed user access token or api key prefixed with cal_",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/DeclineBookingInput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GetBookingOutput_2024_08_13"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Bookings"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/calendars/ics-feed/save": {
|
||||
"post": {
|
||||
"operationId": "CalendarsController_createIcsFeed",
|
||||
@@ -4214,97 +4438,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/oauth/{clientId}/authorize": {
|
||||
"post": {
|
||||
"operationId": "OAuthFlowController_authorize",
|
||||
"summary": "Authorize an OAuth client",
|
||||
"description": "Redirects the user to the specified 'redirect_uri' with an authorization code in query parameter if the client is authorized successfully. The code is then exchanged for access and refresh tokens via the `/exchange` endpoint.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "clientId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/OAuthAuthorizeInput"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The user is redirected to the 'redirect_uri' with an authorization code in query parameter e.g. `redirectUri?code=secretcode.`"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request if the OAuth client is not found, if the redirect URI is invalid, or if the user has already authorized the client."
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"OAuth"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/oauth/{clientId}/exchange": {
|
||||
"post": {
|
||||
"operationId": "OAuthFlowController_exchange",
|
||||
"summary": "Exchange authorization code for access tokens",
|
||||
"description": "Exchanges the authorization code received from the `/authorize` endpoint for access and refresh tokens. The authorization code should be provided in the 'Authorization' header prefixed with 'Bearer '.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Authorization",
|
||||
"required": true,
|
||||
"in": "header",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "clientId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ExchangeAuthorizationCodeInput"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successfully exchanged authorization code for access and refresh tokens.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/KeysResponseDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request if the authorization code is missing, invalid, or if the client ID and secret do not match."
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"OAuth"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/oauth/{clientId}/refresh": {
|
||||
"post": {
|
||||
"operationId": "OAuthFlowController_refreshAccessToken",
|
||||
@@ -5033,6 +5166,37 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/stripe/check/{teamId}": {
|
||||
"get": {
|
||||
"operationId": "StripeController_checkTeamStripeConnection",
|
||||
"summary": "Check team stripe connection",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "teamId",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/StripCredentialsCheckOutputResponseDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Stripe"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/timezones": {
|
||||
"get": {
|
||||
"operationId": "TimezonesController_getTimeZones",
|
||||
@@ -5088,7 +5252,8 @@
|
||||
},
|
||||
"get": {
|
||||
"operationId": "WebhooksController_getWebhooks",
|
||||
"summary": "Get all webooks (paginated)",
|
||||
"summary": "Get all webooks",
|
||||
"description": "Gets a paginated list of webhooks for the authenticated user.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "take",
|
||||
@@ -5818,28 +5983,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"OAuthAuthorizeInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"redirectUri": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"redirectUri"
|
||||
]
|
||||
},
|
||||
"ExchangeAuthorizationCodeInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"clientSecret": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"clientSecret"
|
||||
]
|
||||
},
|
||||
"RefreshTokenInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6720,6 +6863,18 @@
|
||||
"type": "number",
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -6943,6 +7098,7 @@
|
||||
},
|
||||
"required": [
|
||||
"lengthInMinutes",
|
||||
"lengthInMinutesOptions",
|
||||
"title",
|
||||
"slug"
|
||||
]
|
||||
@@ -8085,6 +8241,18 @@
|
||||
"type": "number",
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -8308,6 +8476,7 @@
|
||||
"required": [
|
||||
"id",
|
||||
"lengthInMinutes",
|
||||
"lengthInMinutesOptions",
|
||||
"title",
|
||||
"slug",
|
||||
"description",
|
||||
@@ -8423,6 +8592,18 @@
|
||||
"type": "number",
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -8643,7 +8824,10 @@
|
||||
"hideCalendarEventDetails": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"lengthInMinutesOptions"
|
||||
]
|
||||
},
|
||||
"UpdateEventTypeOutput_2024_06_14": {
|
||||
"type": "object",
|
||||
@@ -9902,6 +10086,18 @@
|
||||
"type": "number",
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -10138,6 +10334,7 @@
|
||||
},
|
||||
"required": [
|
||||
"lengthInMinutes",
|
||||
"lengthInMinutesOptions",
|
||||
"title",
|
||||
"slug",
|
||||
"schedulingType",
|
||||
@@ -10219,6 +10416,19 @@
|
||||
"minimum": 1,
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -10644,6 +10854,18 @@
|
||||
"type": "number",
|
||||
"example": 60
|
||||
},
|
||||
"lengthInMinutesOptions": {
|
||||
"example": [
|
||||
15,
|
||||
30,
|
||||
60
|
||||
],
|
||||
"description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Learn the secrets of masterchief!"
|
||||
@@ -10874,7 +11096,10 @@
|
||||
"type": "boolean",
|
||||
"description": "If true, all current and future team members will be assigned to this event type"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"lengthInMinutesOptions"
|
||||
]
|
||||
},
|
||||
"UpdateTeamEventTypeOutput": {
|
||||
"type": "object",
|
||||
@@ -12584,6 +12809,11 @@
|
||||
"description": "The start time of the booking in ISO 8601 format in UTC timezone.",
|
||||
"example": "2024-08-13T09:00:00Z"
|
||||
},
|
||||
"lengthInMinutes": {
|
||||
"type": "number",
|
||||
"example": 30,
|
||||
"description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking."
|
||||
},
|
||||
"eventTypeId": {
|
||||
"type": "number",
|
||||
"description": "The ID of the event type that is booked.",
|
||||
@@ -12629,6 +12859,7 @@
|
||||
},
|
||||
"required": [
|
||||
"start",
|
||||
"lengthInMinutes",
|
||||
"eventTypeId",
|
||||
"attendee"
|
||||
]
|
||||
@@ -12641,6 +12872,11 @@
|
||||
"description": "The start time of the booking in ISO 8601 format in UTC timezone.",
|
||||
"example": "2024-08-13T09:00:00Z"
|
||||
},
|
||||
"lengthInMinutes": {
|
||||
"type": "number",
|
||||
"example": 30,
|
||||
"description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking."
|
||||
},
|
||||
"eventTypeId": {
|
||||
"type": "number",
|
||||
"description": "The ID of the event type that is booked.",
|
||||
@@ -12691,6 +12927,7 @@
|
||||
},
|
||||
"required": [
|
||||
"start",
|
||||
"lengthInMinutes",
|
||||
"eventTypeId",
|
||||
"attendee",
|
||||
"instant"
|
||||
@@ -12704,6 +12941,11 @@
|
||||
"description": "The start time of the booking in ISO 8601 format in UTC timezone.",
|
||||
"example": "2024-08-13T09:00:00Z"
|
||||
},
|
||||
"lengthInMinutes": {
|
||||
"type": "number",
|
||||
"example": 30,
|
||||
"description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking."
|
||||
},
|
||||
"eventTypeId": {
|
||||
"type": "number",
|
||||
"description": "The ID of the event type that is booked.",
|
||||
@@ -12754,6 +12996,7 @@
|
||||
},
|
||||
"required": [
|
||||
"start",
|
||||
"lengthInMinutes",
|
||||
"eventTypeId",
|
||||
"attendee"
|
||||
]
|
||||
@@ -13278,6 +13521,78 @@
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"ReassignedToDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"example": 123
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "John Doe"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"ReassignBookingOutput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"example": "success",
|
||||
"enum": [
|
||||
"success",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13"
|
||||
}
|
||||
],
|
||||
"description": "Booking data, which can be either a ReassignAutoBookingOutput object or a ReassignManualBookingOutput object",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"ReassignToUserBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"example": "Host has to take another call",
|
||||
"description": "Reason for reassigning the booking"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DeclineBookingInput_2024_08_13": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"example": "Host has to take another call",
|
||||
"description": "Reason for declining a booking that requires a confirmation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReserveSlotInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -23,6 +23,14 @@ export class PlatformBillingRepositoryFixture {
|
||||
});
|
||||
}
|
||||
|
||||
async get(orgId: number) {
|
||||
return this.prismaWriteClient.platformBilling.findFirst({
|
||||
where: {
|
||||
id: orgId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async deleteSubscriptionForTeam(teamId: number) {
|
||||
// silently try to delete the subscription
|
||||
try {
|
||||
|
||||
@@ -40,6 +40,8 @@ function PageWrapper(props: AppProps) {
|
||||
pageStatus = "404";
|
||||
} else if (router.pathname === "/500") {
|
||||
pageStatus = "500";
|
||||
} else if (router.pathname === "/403") {
|
||||
pageStatus = "403";
|
||||
}
|
||||
|
||||
// On client side don't let nonce creep into DOM
|
||||
|
||||
@@ -31,6 +31,8 @@ function PageWrapper(props: PageWrapperProps) {
|
||||
pageStatus = "404";
|
||||
} else if (pathname === "/500") {
|
||||
pageStatus = "500";
|
||||
} else if (pathname === "/403") {
|
||||
pageStatus = "403";
|
||||
}
|
||||
|
||||
// On client side don't let nonce creep into DOM
|
||||
|
||||
@@ -132,6 +132,7 @@ function BookingListItem(booking: BookingItemProps) {
|
||||
});
|
||||
|
||||
const isUpcoming = new Date(booking.endTime) >= new Date();
|
||||
const isOngoing = isUpcoming && new Date() >= new Date(booking.startTime);
|
||||
const isBookingInPast = new Date(booking.endTime) < new Date();
|
||||
const isCancelled = booking.status === BookingStatus.CANCELLED;
|
||||
const isConfirmed = booking.status === BookingStatus.ACCEPTED;
|
||||
@@ -269,7 +270,7 @@ function BookingListItem(booking: BookingItemProps) {
|
||||
});
|
||||
}
|
||||
|
||||
if (isBookingInPast) {
|
||||
if (isBookingInPast || isOngoing) {
|
||||
editBookingActions.push({
|
||||
id: "no_show",
|
||||
label: t("mark_as_no_show"),
|
||||
|
||||
@@ -8,12 +8,12 @@ type IndividualPlatformPlan = {
|
||||
// if pricing or plans change in future modify this
|
||||
export const platformPlans: IndividualPlatformPlan[] = [
|
||||
{
|
||||
plan: "Starter",
|
||||
plan: "Free",
|
||||
description:
|
||||
"Perfect for just getting started with community support and access to hosted platform APIs, Cal.com Atoms (React components) and more.",
|
||||
pricing: 99,
|
||||
"The best plan to dip your toes into scheduling infrastructure. Start immediately with 25 free meetings per month",
|
||||
pricing: 0,
|
||||
includes: [
|
||||
"Up to 100 bookings a month",
|
||||
"Up to 25 bookings a month",
|
||||
"$0.99 overage beyond",
|
||||
"Community Support",
|
||||
"Cal Atoms (React Library)",
|
||||
|
||||
@@ -37,7 +37,7 @@ export const PlatformBillingCard = ({
|
||||
</h1>
|
||||
<p className="pb-5 pt-3 text-base">{description}</p>
|
||||
<h1 className="text-3xl font-semibold">
|
||||
{pricing && (
|
||||
{pricing !== undefined && (
|
||||
<>
|
||||
US${pricing} <span className="text-sm">per month</span>
|
||||
</>
|
||||
@@ -50,7 +50,7 @@ export const PlatformBillingCard = ({
|
||||
loading={isLoading}
|
||||
onClick={handleSubscribe}
|
||||
className="flex w-[100%] items-center justify-center">
|
||||
{pricing ? "Subscribe" : "Schedule a time"}
|
||||
{pricing !== undefined ? "Subscribe" : "Schedule a time"}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -21,12 +21,13 @@ type HelpCardInfo = {
|
||||
// if pricing or plans change in future modify this
|
||||
export const platformPlans: IndividualPlatformPlan[] = [
|
||||
{
|
||||
plan: "Starter",
|
||||
plan: "Free",
|
||||
description:
|
||||
"Perfect for just getting started with community support and access to hosted platform APIs, Cal.com Atoms (React components) and more.",
|
||||
pricing: 99,
|
||||
"The best plan to dip your toes into scheduling infrastructure. Start immediately with 25 free meetings per month",
|
||||
pricing: 0,
|
||||
includes: [
|
||||
"Up to 100 bookings a month",
|
||||
"Up to 25 bookings a month",
|
||||
"$0.99 overage beyond",
|
||||
"Community Support",
|
||||
"Cal Atoms (React Library)",
|
||||
"Platform APIs",
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import type { ParsedUrlQuery } from "querystring";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getCRMContactOwnerForRRLeadSkip } from "@calcom/app-store/_utils/CRMRoundRobinSkip";
|
||||
import { ROUTING_FORM_RESPONSE_ID_QUERY_STRING } from "@calcom/app-store/routing-forms/lib/constants";
|
||||
import { enabledAppSlugs } from "@calcom/app-store/routing-forms/lib/enabledApps";
|
||||
import { zodRoutes as routesSchema } from "@calcom/app-store/routing-forms/zod";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||
import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booking";
|
||||
@@ -79,6 +83,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
}
|
||||
|
||||
const eventData = team.eventTypes[0];
|
||||
const eventTypeId = eventData.id;
|
||||
|
||||
let booking: GetBookingType | null = null;
|
||||
if (rescheduleUid) {
|
||||
@@ -92,7 +97,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
return {
|
||||
props: {
|
||||
eventData: {
|
||||
eventTypeId: eventData.id,
|
||||
eventTypeId,
|
||||
entity: {
|
||||
fromRedirectOfNonOrgLink,
|
||||
considerUnpublished: isUnpublished && !fromRedirectOfNonOrgLink,
|
||||
@@ -112,21 +117,133 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
isInstantMeeting: eventData && queryIsInstantMeeting ? true : false,
|
||||
themeBasis: null,
|
||||
orgBannerUrl: team.parent?.bannerUrl ?? "",
|
||||
teamMemberEmail: await getTeamMemberEmail(eventData, email as string),
|
||||
teamMemberEmail: await handleGettingTeamMemberEmail(query, eventTypeId, eventData),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
async function getTeamMemberEmail(
|
||||
eventData: {
|
||||
id: number;
|
||||
isInstantEvent: boolean;
|
||||
schedulingType: SchedulingType | null;
|
||||
metadata: Prisma.JsonValue | null;
|
||||
length: number;
|
||||
},
|
||||
email?: string
|
||||
): Promise<string | null> {
|
||||
interface EventData {
|
||||
id: number;
|
||||
isInstantEvent: boolean;
|
||||
schedulingType: SchedulingType | null;
|
||||
metadata: Prisma.JsonValue | null;
|
||||
length: number;
|
||||
}
|
||||
|
||||
async function handleGettingTeamMemberEmail(
|
||||
query: ParsedUrlQuery,
|
||||
eventTypeId: number,
|
||||
eventData: EventData
|
||||
) {
|
||||
if (
|
||||
!query.email ||
|
||||
typeof query.email !== "string" ||
|
||||
eventData.schedulingType !== SchedulingType.ROUND_ROBIN
|
||||
)
|
||||
return null;
|
||||
|
||||
// Check if a routing form was completed and an routing form option is enabled
|
||||
if (
|
||||
ROUTING_FORM_RESPONSE_ID_QUERY_STRING in query &&
|
||||
Object.values(query).some((value) => value === "true")
|
||||
) {
|
||||
const { email, skipContactOwner } = await handleRoutingFormOption(query, eventTypeId);
|
||||
|
||||
if (skipContactOwner) return null;
|
||||
if (email) return email;
|
||||
} else {
|
||||
return await getTeamMemberEmail(eventData, query.email);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function handleRoutingFormOption(query: ParsedUrlQuery, eventTypeId: number) {
|
||||
const nullReturnValue = { email: null, skipContactOwner: false };
|
||||
|
||||
if (typeof query.email !== "string") return nullReturnValue;
|
||||
|
||||
const routingFormQuery = await prisma.app_RoutingForms_Form.findFirst({
|
||||
where: {
|
||||
responses: {
|
||||
some: {
|
||||
id: Number(query[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]),
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
routes: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!routingFormQuery || !routingFormQuery?.routes) return nullReturnValue;
|
||||
|
||||
const parsedRoutes = routesSchema.safeParse(routingFormQuery.routes);
|
||||
|
||||
if (!parsedRoutes.success || !parsedRoutes.data) return nullReturnValue;
|
||||
|
||||
// Find the route with the attributeRoutingConfig
|
||||
const route = parsedRoutes.data.find((route) => {
|
||||
if ("action" in route) {
|
||||
return route.action.eventTypeId === eventTypeId;
|
||||
}
|
||||
});
|
||||
|
||||
if (!route || !("attributeRoutingConfig" in route)) return nullReturnValue;
|
||||
|
||||
// Get attributeRoutingConfig for the form
|
||||
const attributeRoutingConfig = route.attributeRoutingConfig;
|
||||
|
||||
if (!attributeRoutingConfig) return nullReturnValue;
|
||||
|
||||
// If the skipContactOwner is enabled then don't return an team member email
|
||||
if (attributeRoutingConfig?.skipContactOwner) return { ...nullReturnValue, skipContactOwner: true };
|
||||
|
||||
// Determine if a routing form enabled app is in the query. Then pass it to the proper handler
|
||||
// Routing form apps will have the format cal.appSlug
|
||||
let enabledRoutingFormApp;
|
||||
|
||||
for (const key of Object.keys(query)) {
|
||||
const keySplit = key.split(".");
|
||||
|
||||
const appSlug = keySplit[1];
|
||||
|
||||
if (enabledAppSlugs.includes(appSlug)) {
|
||||
enabledRoutingFormApp = appSlug;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabledRoutingFormApp) return nullReturnValue;
|
||||
|
||||
const appBookingFormHandler = (await import("@calcom/app-store/routing-forms/appBookingFormHandler"))
|
||||
.default;
|
||||
const appHandler = appBookingFormHandler[enabledRoutingFormApp];
|
||||
|
||||
if (!appHandler) return nullReturnValue;
|
||||
|
||||
const { email: userEmail } = await appHandler(query.email, attributeRoutingConfig, eventTypeId);
|
||||
|
||||
if (!userEmail) return nullReturnValue;
|
||||
|
||||
// Determine if the user is a part of the event type
|
||||
const userQuery = await await prisma.user.findFirst({
|
||||
where: {
|
||||
email: userEmail,
|
||||
hosts: {
|
||||
some: {
|
||||
eventTypeId: eventTypeId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!userQuery) return nullReturnValue;
|
||||
|
||||
return { ...nullReturnValue, email: userEmail };
|
||||
}
|
||||
|
||||
async function getTeamMemberEmail(eventData: EventData, email: string): Promise<string | null> {
|
||||
// Pre-requisites
|
||||
if (!eventData || !email || eventData.schedulingType !== SchedulingType.ROUND_ROBIN) return null;
|
||||
const crmContactOwnerEmail = await getCRMContactOwnerForRRLeadSkip(email, eventData.metadata);
|
||||
|
||||
@@ -315,8 +315,23 @@ export default function Success(props: PageProps) {
|
||||
return t(`needs_to_be_confirmed_or_rejected${titleSuffix}`);
|
||||
}
|
||||
if (bookingInfo.user) {
|
||||
return t(`${titlePrefix}emailed_you_and_attendees${titleSuffix}`, {
|
||||
user: bookingInfo.user.name || bookingInfo.user.email,
|
||||
const isHost = bookingInfo.user.id === session?.user?.id;
|
||||
const isAttendee = bookingInfo.attendees.find((attendee) => attendee.email === session?.user?.email);
|
||||
const attendee = bookingInfo.attendees[0]?.name || bookingInfo.attendees[0]?.email || "Nameless";
|
||||
const host = bookingInfo.user.name || bookingInfo.user.email;
|
||||
if (isHost) {
|
||||
return t(`${titlePrefix}emailed_you_and_attendees${titleSuffix}`, {
|
||||
user: attendee,
|
||||
});
|
||||
}
|
||||
if (isAttendee) {
|
||||
return t(`${titlePrefix}emailed_you_and_attendees${titleSuffix}`, {
|
||||
user: host,
|
||||
});
|
||||
}
|
||||
return t(`${titlePrefix}emailed_host_and_attendee${titleSuffix}`, {
|
||||
host,
|
||||
attendee,
|
||||
});
|
||||
}
|
||||
return t(`emailed_you_and_attendees${titleSuffix}`);
|
||||
|
||||
@@ -81,7 +81,7 @@ interface InfiniteEventTypeListProps {
|
||||
group: InfiniteEventTypeGroup;
|
||||
readOnly: boolean;
|
||||
bookerUrl: string | null;
|
||||
pages: { nextCursor: number | undefined; eventTypes: InfiniteEventType[] }[] | undefined;
|
||||
pages: { nextCursor: number | null | undefined; eventTypes: InfiniteEventType[] }[] | undefined;
|
||||
lockedByOrg?: boolean;
|
||||
isPending?: boolean;
|
||||
debouncedSearchTerm?: string;
|
||||
@@ -349,9 +349,14 @@ export const InfiniteEventTypeList = ({
|
||||
group: { teamId: group?.teamId, parentId: group?.parentId },
|
||||
},
|
||||
(data) => {
|
||||
if (!data) return { pages: [], pageParams: [] };
|
||||
|
||||
return {
|
||||
pageParams: data?.pageParams ?? [],
|
||||
pages: newOrder,
|
||||
...data,
|
||||
pages: newOrder.map((page) => ({
|
||||
...page,
|
||||
nextCursor: page.nextCursor ?? undefined,
|
||||
})),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@calcom/web",
|
||||
"version": "4.6.19",
|
||||
"version": "4.6.24",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"analyze": "ANALYZE=true next build",
|
||||
@@ -74,7 +74,7 @@
|
||||
"@upstash/redis": "^1.21.0",
|
||||
"@vercel/edge-config": "^0.1.1",
|
||||
"@vercel/edge-functions-ui": "^0.2.1",
|
||||
"@vercel/og": "^0.5.0",
|
||||
"@vercel/og": "^0.6.3",
|
||||
"accept-language-parser": "^1.5.0",
|
||||
"async": "^3.2.4",
|
||||
"bcp-47-match": "^2.0.3",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import Head from "next/head";
|
||||
|
||||
import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Button } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
export default function AccessDenied() {
|
||||
const { t } = useLocale();
|
||||
|
||||
return (
|
||||
<div className="bg-subtle flex h-screen">
|
||||
<Head>
|
||||
<title>{`${t("access_denied")} | ${APP_NAME}`}</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<div className="rtl: bg-default m-auto rounded-md p-10 text-right ltr:text-left">
|
||||
<h1 className="font-cal text-emphasis text-6xl">403</h1>
|
||||
<h2 className="text-emphasis mt-6 text-2xl font-medium">{t("dont_have_access_this_page")}</h2>
|
||||
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">
|
||||
{t("you_need_admin_or_owner_privileges_to_access")}
|
||||
</p>
|
||||
<Button href={WEBAPP_URL}>{t("go_back_home")}</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
AccessDenied.PageWrapper = PageWrapper;
|
||||
@@ -83,7 +83,7 @@ export default async function handler(req: NextApiRequest) {
|
||||
/>
|
||||
),
|
||||
ogConfig
|
||||
) as { body: Buffer };
|
||||
);
|
||||
|
||||
return new Response(img.body, {
|
||||
status: 200,
|
||||
@@ -97,9 +97,7 @@ export default async function handler(req: NextApiRequest) {
|
||||
slug: searchParams.get("slug"),
|
||||
imageType,
|
||||
});
|
||||
const img = new ImageResponse(<App name={name} description={description} slug={slug} />, ogConfig) as {
|
||||
body: Buffer;
|
||||
};
|
||||
const img = new ImageResponse(<App name={name} description={description} slug={slug} />, ogConfig);
|
||||
|
||||
return new Response(img.body, { status: 200, headers: { "Content-Type": "image/png" } });
|
||||
}
|
||||
@@ -111,9 +109,7 @@ export default async function handler(req: NextApiRequest) {
|
||||
imageType,
|
||||
});
|
||||
|
||||
const img = new ImageResponse(<Generic title={title} description={description} />, ogConfig) as {
|
||||
body: Buffer;
|
||||
};
|
||||
const img = new ImageResponse(<Generic title={title} description={description} />, ogConfig);
|
||||
|
||||
return new Response(img.body, { status: 200, headers: { "Content-Type": "image/png" } });
|
||||
}
|
||||
|
||||
@@ -80,9 +80,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
},
|
||||
});
|
||||
|
||||
// Sync Services: Close.com
|
||||
// closeComUpdateTeam(prevTeam, team);
|
||||
|
||||
// redirect to team screen
|
||||
res.redirect(302, `/settings/teams/${team.id}/onboard-members?event=team_created`);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 221 KiB After Width: | Height: | Size: 221 KiB |
@@ -161,6 +161,10 @@
|
||||
<symbol class="lucide lucide-chevron-up" viewBox="0 0 24 24" fill="inherit" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="chevron-up">
|
||||
<path d="m18 15-6-6-6 6" ></path>
|
||||
</symbol>
|
||||
<symbol class="lucide lucide-chevrons-down-up" viewBox="0 0 24 24" fill="inherit" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="chevrons-down-up">
|
||||
<path d="m7 20 5-5 5 5" ></path>
|
||||
<path d="m7 4 5 5 5-5" ></path>
|
||||
</symbol>
|
||||
<symbol class="lucide lucide-chevrons-left" viewBox="0 0 24 24" fill="inherit" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="chevrons-left">
|
||||
<path d="m11 17-5-5 5-5" ></path>
|
||||
<path d="m18 17-5-5 5-5" ></path>
|
||||
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "الإجراء المطلوب إعادة الجدولة: يُرجى حجز وقت جديد لمدة {{eventType}} مع {{name}}",
|
||||
"hi_user_name": "مرحبا {{name}}",
|
||||
"ics_event_title": "{{eventType}} مع {{name}}",
|
||||
"please_book_a_time_sometime_later": "عفواً، لم نتمكن من الاتصال بك هذه المرة. الرجاء جدولة مكالمة مستقبلية بدلاً من ذلك",
|
||||
"please_book_a_time_sometime_later": "يبدو أن جميع خبرائنا مشغولون حاليًا. يرجى تحديد موعد مكالمة في الوقت الذي يناسبك وسنكون جاهزين لمساعدتك.",
|
||||
"schedule_instead": "حدد موعدًا بدلاً من ذلك",
|
||||
"new_event_subject": "حدث جديد: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "الانضمام بواسطة {{entryPoint}}",
|
||||
"notes": "ملاحظات",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "آخر",
|
||||
"email_sign_in_subject": "رابط تسجيل الدخول بك لـ{{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "أنت تجتمع مع {{user}}. أرسلنا بريداً إلكترونياً مع دعوة اجتماع بكل التفاصيل إلى الجميع.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} سيجتمع مع {{attendee}}. لقد أرسلنا بريداً إلكترونياً يحتوي على دعوة تقويم مع كافة التفاصيل للجميع.",
|
||||
"emailed_you_and_attendees": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة للتقويم عبر البريد الإلكتروني تتضمن كل التفاصيل.",
|
||||
"emailed_host_and_attendee": "لقد أرسلنا بريداً إلكترونياً يحتوي على دعوة تقويم مع كافة التفاصيل للجميع.",
|
||||
"emailed_you_and_attendees_recurring": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة تقويم عبر البريد الإلكتروني لأول هذه الأحداث المتكررة.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "أنت تجتمع مع {{user}}. أرسلنا بريداً إلكترونياً مع دعوة اجتماع بكل التفاصيل إلى الجميع لأول اجتماع من هذه الاجتماعات الدورية.",
|
||||
"emailed_host_and_attendee_recurring": "لقد أرسلنا بريداً إلكترونياً يحتوي على دعوة تقويم مع كافة التفاصيل للجميع للحدث الأول من هذه الأحداث المتكررة.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "أنت على موعد مع {{user}}. لقد أرسلنا بريداً إلكترونياً يحتوي على دعوة تقويم مع كافة التفاصيل للجميع للحدث الأول من هذه الأحداث المتكررة.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} سيجتمع مع {{attendee}}. لقد أرسلنا بريداً إلكترونياً يحتوي على دعوة تقويم مع كافة التفاصيل للجميع للحدث الأول من هذه الأحداث المتكررة.",
|
||||
"emailed_you_and_any_other_attendees": "تم إرسال هذه المعلومات إليك وإلى الحضور الآخرين عبر البريد الإلكتروني.",
|
||||
"needs_to_be_confirmed_or_rejected": "لا يزال الحجز الخاص بك يحتاج إلى التأكيد أو الرفض.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "لا يزال الاجتماع المتكرر الخاص بك بحاجة إلى التأكيد أو الرفض.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "ليس لديك أي فرق حتى الآن.",
|
||||
"no_teams_description": "تسمح الفرق للآخرين بحجز الأحداث المشتركة بين زملائك في العمل.",
|
||||
"submit": "إرسال",
|
||||
"confirm_remove_attribute": "نعم، إزالة السمة",
|
||||
"remove_attribute": "إزالة السمة",
|
||||
"remove_attribute_confirmation_message": "هل أنت متأكد أنك تريد إزالة السمة '{{name}}'؟ سيتم إلغاء تعيين جميع المستخدمين المعينين لها حالياً.",
|
||||
"delete": "حذف",
|
||||
"update": "تحديث",
|
||||
"save": "حفظ",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "حدّد بعض الفترات المتاحة وأدرجها في رسالتك الإلكترونية",
|
||||
"select_time": "اختيار الوقت",
|
||||
"select_date": "اختيار التاريخ",
|
||||
"connecting_you_to_someone": "نقوم بربطك بشخص ما.",
|
||||
"connecting_you_to_someone": "نقوم بربطك بشخص من {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "من فضلك لا تغلق أو تحدّث هذه الصفحة",
|
||||
"see_all_available_times": "رؤية كل الأوقات المتاحة",
|
||||
"org_team_names_example_1": "مثال، فريق التسويق",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "معلومات وقت انتهاء الحدث في المنطقة الزمنية للحاضر",
|
||||
"salesforce_create_event_on_contact": "إنشاء حدث على جهة الاتصال، إذا كانت موجودة. وإلا، الرجوع إلى العميل المحتمل",
|
||||
"salesforce_owner_name_to_change": "اسم المالك المراد تغييره",
|
||||
"dont_have_access_this_page": "ليس لديك صلاحية الوصول إلى هذه الصفحة",
|
||||
"you_need_admin_or_owner_privileges_to_access": "لرؤية هذه الصفحة أو التفاعل معها، يجب أن تكون لديك صلاحيات المدير أو المالك",
|
||||
"field_type": "نوع الحقل",
|
||||
"when_to_write": "متى تتم الكتابة",
|
||||
"salesforce_on_booking_write_to_record": "عند الحجز، اكتب في حقل مخصص في سجل الحاضر {{record}}",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "تاريخ بدء الحجز",
|
||||
"booking_created_date": "تاريخ إنشاء الحجز",
|
||||
"booking_reassigned_to_host": "تم إعادة تعيين الحجز إلى {{host}}",
|
||||
"access_denied": "تم رفض الوصول",
|
||||
"salesforce_route_to_owner": "سيكون مالك جهة الاتصال هو مضيف Round Robin إذا كان متاحاً",
|
||||
"salesforce_do_not_route_to_owner": "لن يتم فرض مالك جهة الاتصال (يمكن أن يظل مضيفاً إذا تطابق مع السمات ومعايير Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "التوجيه إلى مستخدم يطابق حقل البحث في الحساب",
|
||||
"salesforce_option": "خيار Salesforce",
|
||||
"lookup_field_name": "اسم حقل البحث",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Təxirə salma tələb olunur: {{eventType}} {{name}} ilə yeni vaxt təyin edin",
|
||||
"hi_user_name": "Salam {{name}}",
|
||||
"ics_event_title": "{{eventType}} {{name}} ilə",
|
||||
"please_book_a_time_sometime_later": "Bağışlayın, bu dəfə əlaqə qura bilmədik. Zəhmət olmasa, gələcək bir zəng üçün vaxt təyin edin",
|
||||
"please_book_a_time_sometime_later": "Görünür ki, hazırda bütün ekspertlərimiz məşğuldur. Zəhmət olmasa, sizə ən uyğun olan vaxtı seçin və biz sizə kömək etməyə hazır olacağıq.",
|
||||
"schedule_instead": "Əvəzində planlaşdırın",
|
||||
"new_event_subject": "Yeni tədbir: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "{{entryPoint}} ilə qoşulun",
|
||||
"notes": "Qeydlər",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Digər",
|
||||
"email_sign_in_subject": "{{appName}} üçün giriş linkiniz",
|
||||
"round_robin_emailed_you_and_attendees": "{{user}} ilə görüşürsünüz. Təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} {{attendee}} ilə görüşür. Təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"emailed_you_and_attendees": "Təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"emailed_host_and_attendee": "Təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"emailed_you_and_attendees_recurring": "Bu təkrarlanan hadisələrin birincisi üçün təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}} ilə görüşürsünüz. Bu təkrarlanan hadisələrin birincisi üçün təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"emailed_host_and_attendee_recurring": "Bu təkrarlanan tədbirlərin birincisi üçün təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Siz {{user}} ilə görüşürsünüz. Bu təkrarlanan tədbirlərin birincisi üçün təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} {{attendee}} ilə görüşür. Bu təkrarlanan tədbirlərin birincisi üçün təfərrüatları olan təqvim dəvəti ilə hər kəsə e-poçt göndərdik.",
|
||||
"emailed_you_and_any_other_attendees": "Bu məlumatla hər kəsə e-poçt göndərdik.",
|
||||
"needs_to_be_confirmed_or_rejected": "Rezervasiyanız hələ də təsdiqlənməli və ya rədd edilməlidir.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Təkrarlanan görüşünüz hələ də təsdiqlənməli və ya rədd edilməlidir.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Hələ heç bir komandanız yoxdur.",
|
||||
"no_teams_description": "Komandalar həmkarlarınız arasında paylaşılan tədbirləri sifariş etməyə imkan verir.",
|
||||
"submit": "Təsdiqlə",
|
||||
"confirm_remove_attribute": "Bəli, atributu sil",
|
||||
"remove_attribute": "Atributu sil",
|
||||
"remove_attribute_confirmation_message": "Atributu '{{name}}' silmək istədiyinizə əminsinizmi? Hazırda ona təyin edilmiş bütün istifadəçilər təyin edilməmiş olacaq.",
|
||||
"delete": "Sil",
|
||||
"update": "Yenilə",
|
||||
"save": "Yadda saxla",
|
||||
@@ -1239,7 +1247,7 @@
|
||||
"number_provided": "Telefon nömrəsi təmin ediləcək",
|
||||
"before_event_trigger": "tədbir başlamazdan əvvəl",
|
||||
"event_cancelled_trigger": "tədbir ləğv edildikdə",
|
||||
"after_hosts_cal_video_no_show": "Ev sahibləri Cal video görüşünə qoşulmadıqdan sonra",
|
||||
"after_hosts_cal_video_no_show": "Təşkilatçılar Cal video görüşünə qoşulmadıqdan sonra",
|
||||
"after_guests_cal_video_no_show": "Qonaqlar Cal video görüşünə qoşulmadıqdan sonra",
|
||||
"new_event_trigger": "yeni tədbir sifariş edildikdə",
|
||||
"email_host_action": "ev sahibinə e-poçt göndərin",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Mövcud vaxtları seçin və Email-ə əlavə edin",
|
||||
"select_time": "Vaxtı Seçin",
|
||||
"select_date": "Tarixi Seçin",
|
||||
"connecting_you_to_someone": "Sizi kiməsə qoşuruq.",
|
||||
"connecting_you_to_someone": "Sizi {{orgName}}-dən birisi ilə əlaqələndiririk.",
|
||||
"please_do_not_close_this_tab": "Zəhmət olmasa, bu səhifəni bağlamayın və ya yeniləməyin",
|
||||
"see_all_available_times": "Bütün mövcud vaxtları görün",
|
||||
"org_team_names_example_1": "məs. Marketinq Komandası",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "İştirakçı Saat Qurşağında Tədbirin Bitmə Vaxtı",
|
||||
"salesforce_create_event_on_contact": "Əgər mövcuddursa, kontakt üzərində hadisə yaradın. Əks halda, lidə qayıdın",
|
||||
"salesforce_owner_name_to_change": "Dəyişdiriləcək sahibin adı",
|
||||
"dont_have_access_this_page": "Bu səhifəyə girişiniz yoxdur",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Bu səhifəni görmək və ya onunla qarşılıqlı əlaqədə olmaq üçün admin və ya sahib imtiyazlarına malik olmalısınız",
|
||||
"field_type": "Sahə növü",
|
||||
"when_to_write": "Nə zaman yazmaq",
|
||||
"salesforce_on_booking_write_to_record": "Rezervasiya zamanı iştirakçının {{record}} qeydinə xüsusi sahəyə yaz",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Rezervasiyanın başlama tarixi",
|
||||
"booking_created_date": "Rezervasiyanın yaradılma tarixi",
|
||||
"booking_reassigned_to_host": "Rezervasiya {{host}}-a yenidən təyin edildi",
|
||||
"access_denied": "Giriş qadağandır",
|
||||
"salesforce_route_to_owner": "Əlaqə sahibi mövcud olduqda Round Robin ev sahibi olacaq",
|
||||
"salesforce_do_not_route_to_owner": "Əlaqə sahibi məcbur edilməyəcək (əgər atributlara və Round Robin meyarlarına uyğun gəlirsə, yenə də ev sahibi ola bilər)",
|
||||
"salesforce_route_to_custom_lookup_field": "Hesabda axtarış sahəsinə uyğun gələn istifadəçiyə yönləndir",
|
||||
"salesforce_option": "Salesforce Seçimi",
|
||||
"lookup_field_name": "Axtarış Sahəsinin Adı",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni sətirləri bura əlavə edin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Akce vyžadovaná k přeplánování: zarezervujte si nový čas pro událost {{eventType}} s osobou {{name}}",
|
||||
"hi_user_name": "Hezký den, {{name}}",
|
||||
"ics_event_title": "{{eventType}} s {{name}}",
|
||||
"please_book_a_time_sometime_later": "Jejda, tentokrát jsme vás nemohli spojit. Prosím, naplánujte si hovor na později.",
|
||||
"please_book_a_time_sometime_later": "Zdá se, že všichni naši experti jsou momentálně zaneprázdněni. Naplánujte si prosím hovor na čas, který vám nejvíce vyhovuje, a my vám rádi pomůžeme.",
|
||||
"schedule_instead": "Naplánovat schůzku",
|
||||
"new_event_subject": "Nová událost: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Připojit se k {{entryPoint}}",
|
||||
"notes": "Poznámky",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Ostatní",
|
||||
"email_sign_in_subject": "Váš přihlašovací odkaz pro {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Setkáte se s {{user}}. Poslali jsme e-mail s pozvánkou do kalendáře a podrobnostmi všem účastníkům.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} se setká s {{attendee}}. Všem jsme poslali e-mail s pozvánkou do kalendáře a podrobnostmi.",
|
||||
"emailed_you_and_attendees": "Poslali jsme vám a ostatním účastníkům e-mail s pozvánkou a podrobnostmi.",
|
||||
"emailed_host_and_attendee": "Všem jsme poslali e-mail s pozvánkou do kalendáře a podrobnostmi.",
|
||||
"emailed_you_and_attendees_recurring": "Na první z těchto opakovaných událostí jsme vám a ostatním účastníkům poslali e-mail s pozvánkou a podrobnostmi.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Setkáte se s {{user}}. Poslali jsme e-mail s pozvánkou do kalendáře a podrobnostmi všem účastníkům pro první z těchto opakujících se událostí.",
|
||||
"emailed_host_and_attendee_recurring": "Všem jsme poslali e-mail s pozvánkou do kalendáře a podrobnostmi pro první z těchto opakujících se událostí.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Setkáte se s {{user}}. Všem jsme poslali e-mail s pozvánkou do kalendáře a podrobnostmi pro první z těchto opakujících se událostí.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} se setká s {{attendee}}. Všem jsme poslali e-mail s pozvánkou do kalendáře a podrobnostmi pro první z těchto opakujících se událostí.",
|
||||
"emailed_you_and_any_other_attendees": "Poslali jsme vám a ostatním účastníkům e-mail s těmito informacemi.",
|
||||
"needs_to_be_confirmed_or_rejected": "Vaše rezervace bude teprve schválena nebo zamítnuta.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Vaše opakovaná schůzka musí být ještě potvrzena nebo zamítnuta.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Zatím nemáte žádné týmy.",
|
||||
"no_teams_description": "Týmy ostatním umožňují rezervovat sdílené události mezi spolupracovníky.",
|
||||
"submit": "Odeslat",
|
||||
"confirm_remove_attribute": "Ano, odstranit atribut",
|
||||
"remove_attribute": "Odstranit atribut",
|
||||
"remove_attribute_confirmation_message": "Opravdu chcete odstranit atribut '{{name}}'? Všichni uživatelé, kteří jsou k němu aktuálně přiřazeni, budou od něj odpojeni.",
|
||||
"delete": "Smazat",
|
||||
"update": "Aktualizovat",
|
||||
"save": "Uložit",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Bude uvedeno telefonní číslo",
|
||||
"before_event_trigger": "před zahájením události",
|
||||
"event_cancelled_trigger": "při zrušení události",
|
||||
"after_hosts_cal_video_no_show": "Po tom, co se hostitelé nepřipojí k cal video",
|
||||
"after_guests_cal_video_no_show": "Po tom, co se hosté nepřipojí k cal video",
|
||||
"after_hosts_cal_video_no_show": "Poté, co se hostitelé nepřipojili k video hovoru",
|
||||
"after_guests_cal_video_no_show": "Poté, co se hosté nepřipojili k video hovoru",
|
||||
"new_event_trigger": "při rezervaci nové události",
|
||||
"email_host_action": "odeslání e-mailu hostiteli",
|
||||
"email_attendee_action": "odeslat e-mail účastníkům",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Vyberte několik dostupných časů a vložte je do e-mailu",
|
||||
"select_time": "Vyberte čas",
|
||||
"select_date": "Vyberte datum",
|
||||
"connecting_you_to_someone": "Spojujeme vás s někým.",
|
||||
"connecting_you_to_someone": "Spojujeme vás s někým z {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Prosím, nezavírejte ani neobnovujte tuto stránku",
|
||||
"see_all_available_times": "Zobrazit všechny dostupné časy",
|
||||
"org_team_names_example_1": "Např. marketingový tým",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Čas konce události v časovém pásmu účastníka",
|
||||
"salesforce_create_event_on_contact": "Vytvořit událost na kontaktu, pokud existuje. Jinak použít lead",
|
||||
"salesforce_owner_name_to_change": "Jméno vlastníka ke změně",
|
||||
"dont_have_access_this_page": "K této stránce nemáte přístup",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Pro zobrazení nebo interakci s touto stránkou musíte mít administrátorská nebo vlastnická práva",
|
||||
"field_type": "Typ pole",
|
||||
"when_to_write": "Kdy zapisovat",
|
||||
"salesforce_on_booking_write_to_record": "Při rezervaci zapsat do vlastního pole záznamu účastníka {{record}}",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Datum začátku rezervace",
|
||||
"booking_created_date": "Datum vytvoření rezervace",
|
||||
"booking_reassigned_to_host": "Rezervace přeřazena hostiteli {{host}}",
|
||||
"access_denied": "Přístup odepřen",
|
||||
"salesforce_route_to_owner": "Vlastník kontaktu bude hostem Round Robin, pokud je k dispozici",
|
||||
"salesforce_do_not_route_to_owner": "Vlastník kontaktu nebude nucen (stále může být hostem, pokud odpovídá atributům a kritériím Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Přiřadit uživateli, který odpovídá vyhledávacímu poli na účtu",
|
||||
"salesforce_option": "Možnost Salesforce",
|
||||
"lookup_field_name": "Název vyhledávacího pole",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Přidejte své nové řetězce nahoru ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Handling Påkrævet Omlægning: Reservér en ny tid for {{eventType}} med {{name}}",
|
||||
"hi_user_name": "Hej {{name}}",
|
||||
"ics_event_title": "{{eventType}} med {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, vi kunne ikke forbinde dig denne gang. Venligst planlæg et opkald på et senere tidspunkt.",
|
||||
"please_book_a_time_sometime_later": "Det ser ud til, at alle vores eksperter er optaget lige nu. Venligst planlæg et opkald på et tidspunkt, der passer dig bedst, så vi er klar til at hjælpe dig.",
|
||||
"schedule_instead": "Planlæg i stedet",
|
||||
"new_event_subject": "Ny begivenhed: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Deltag via {{entryPoint}}",
|
||||
"notes": "Noter",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Flere",
|
||||
"email_sign_in_subject": "Dit login link til {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Du mødes med {{user}}. Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} mødes med {{attendee}}. Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle.",
|
||||
"emailed_you_and_attendees": "Vi har sendt dig og de andre deltagere en kalenderinvitation med alle detaljerne.",
|
||||
"emailed_host_and_attendee": "Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle.",
|
||||
"emailed_you_and_attendees_recurring": "Vi har sendt dig og de andre deltagere en kalenderinvitation til den første af disse tilbagevendende begivenheder.",
|
||||
"emailed_host_and_attendee_recurring": "Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle for den første af disse tilbagevendende begivenheder.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Du mødes med {{user}}. Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle for den første af disse tilbagevendende begivenheder.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} mødes med {{attendee}}. Vi har sendt en e-mail med en kalenderinvitation med detaljerne til alle for den første af disse tilbagevendende begivenheder.",
|
||||
"emailed_you_and_any_other_attendees": "Du og eventuelle andre deltagere er blevet mailet med disse oplysninger.",
|
||||
"needs_to_be_confirmed_or_rejected": "Din booking mangler stadig at blive bekræftet eller afvist.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Dit tilbagevendende møde mangler stadig at blive bekræftet eller afvist.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Du har ikke nogen teams endnu.",
|
||||
"no_teams_description": "Teams giver andre mulighed for at booke begivenheder, der deles mellem dine kolleger.",
|
||||
"submit": "Videre",
|
||||
"confirm_remove_attribute": "Ja, fjern attribut",
|
||||
"remove_attribute": "Fjern attribut",
|
||||
"remove_attribute_confirmation_message": "Er du sikker på, at du vil fjerne attributten '{{name}}'? Alle brugere, der i øjeblikket er tildelt den, vil blive frakoblet.",
|
||||
"delete": "Slet",
|
||||
"update": "Opdatér",
|
||||
"save": "Gem",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefonnummer vil blive angivet",
|
||||
"before_event_trigger": "før begivenheden starter",
|
||||
"event_cancelled_trigger": "når begivenheden er aflyst",
|
||||
"after_hosts_cal_video_no_show": "Efter værter ikke deltager i cal video",
|
||||
"after_guests_cal_video_no_show": "Efter gæster ikke deltager i cal video",
|
||||
"after_hosts_cal_video_no_show": "Efter værterne ikke deltog i cal-videomødet",
|
||||
"after_guests_cal_video_no_show": "Efter gæsterne ikke deltog i cal-videomødet",
|
||||
"new_event_trigger": "når ny begivenhed er booket",
|
||||
"email_host_action": "send e-mail til vært",
|
||||
"email_attendee_action": "send e-mail til deltagere",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Vælg nogle tilgængelige tidspunkter og indlejre dem i din e-mail",
|
||||
"select_time": "Vælg tid",
|
||||
"select_date": "Vælg dato",
|
||||
"connecting_you_to_someone": "Vi forbinder dig med en person.",
|
||||
"connecting_you_to_someone": "Vi forbinder dig med en person fra {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Luk eller opdater venligst ikke denne side",
|
||||
"see_all_available_times": "Se alle tilgængelige tidspunkter",
|
||||
"org_team_names_example_1": "f.eks. Marketingteam",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Begivenhedens sluttidspunkt i deltagers tidszone",
|
||||
"salesforce_create_event_on_contact": "Opret begivenhed på kontakt, hvis den eksisterer. Ellers fald tilbage til lead",
|
||||
"salesforce_owner_name_to_change": "Ejernavn der skal ændres",
|
||||
"dont_have_access_this_page": "Du har ikke adgang til denne side",
|
||||
"you_need_admin_or_owner_privileges_to_access": "For at kunne se eller interagere med denne side, skal du have administrator- eller ejerrettigheder",
|
||||
"field_type": "Felttype",
|
||||
"when_to_write": "Hvornår der skal skrives",
|
||||
"salesforce_on_booking_write_to_record": "Ved booking, skriv til et brugerdefineret felt på deltagerens {{record}}-post",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Bookings startdato",
|
||||
"booking_created_date": "Dato for oprettelse af booking",
|
||||
"booking_reassigned_to_host": "Booking omfordelt til {{host}}",
|
||||
"access_denied": "Adgang nægtet",
|
||||
"salesforce_route_to_owner": "Kontaktens ejer vil være Round Robin-vært, hvis tilgængelig",
|
||||
"salesforce_do_not_route_to_owner": "Kontaktens ejer vil ikke blive tvunget (kan stadig være vært, hvis det matcher attributterne og Round Robin-kriterierne)",
|
||||
"salesforce_route_to_custom_lookup_field": "Rute til en bruger, der matcher et opslagfelt på en konto",
|
||||
"salesforce_option": "Salesforce-indstilling",
|
||||
"lookup_field_name": "Opslagsfeltnavn",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Tilføj dine nye strenge ovenfor her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Aktion erforderlich - Neuplanung: Bitte buchen Sie eine neue Zeit für „{{eventType}}“ mit {{name}}",
|
||||
"hi_user_name": "Hallo, {{name}}",
|
||||
"ics_event_title": "{{eventType}} mit {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, wir konnten Sie dieses Mal nicht verbinden. Bitte planen Sie stattdessen einen zukünftigen Anruf",
|
||||
"please_book_a_time_sometime_later": "Es scheint, dass alle unsere Experten momentan beschäftigt sind. Bitte vereinbaren Sie einen Termin zu einem Zeitpunkt, der Ihnen am besten passt, und wir werden bereit sein, Ihnen zu helfen.",
|
||||
"schedule_instead": "Stattdessen planen",
|
||||
"new_event_subject": "Neuer Termin: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "{{entryPoint}} beitreten",
|
||||
"notes": "Notizen",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Sonstige",
|
||||
"email_sign_in_subject": "Ihr Anmelde-Link für {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Sie treffen sich mit {{user}}. Wir haben eine E-Mail mit einer Kalendereinladung mit den Details an alle gesendet.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} trifft sich mit {{attendee}}. Wir haben allen eine E-Mail mit einer Kalendereinladung und den Details gesendet.",
|
||||
"emailed_you_and_attendees": "Wir haben eine E-Mail mit einer Kalendereinladung mit den Details an alle gesendet.",
|
||||
"emailed_host_and_attendee": "Wir haben allen eine E-Mail mit einer Kalendereinladung und den Details gesendet.",
|
||||
"emailed_you_and_attendees_recurring": "Wir haben eine E-Mail mit einer Kalendereinladung mit den Details für das erste dieser wiederkehrenden Termine an alle gesendet.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Sie treffen sich mit {{user}}. Wir haben eine E-Mail mit einer Kalendereinladung mit den Details für das erste dieser wiederkehrenden Termine an alle gesendet.",
|
||||
"emailed_host_and_attendee_recurring": "Wir haben allen eine E-Mail mit einer Kalendereinladung und den Details für das erste dieser wiederkehrenden Events gesendet.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Sie treffen sich mit {{user}}. Wir haben allen eine E-Mail mit einer Kalendereinladung und den Details für das erste dieser wiederkehrenden Events gesendet.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} trifft sich mit {{attendee}}. Wir haben allen eine E-Mail mit einer Kalendereinladung und den Details für das erste dieser wiederkehrenden Events gesendet.",
|
||||
"emailed_you_and_any_other_attendees": "Wir haben eine E-Mail mit diesen Informationen an alle gesendet.",
|
||||
"needs_to_be_confirmed_or_rejected": "Ihr Termin muss noch bestätigt oder abgelehnt werden.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Ihr wiederkehrender Termin muss noch bestätigt oder abgelehnt werden.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Sie haben noch keine Teams.",
|
||||
"no_teams_description": "Teams ermöglichen Termine zu buchen, an denen mehrere Mitarbeiter beteiligt sind.",
|
||||
"submit": "Abschicken",
|
||||
"confirm_remove_attribute": "Ja, Attribut entfernen",
|
||||
"remove_attribute": "Attribut entfernen",
|
||||
"remove_attribute_confirmation_message": "Sind Sie sicher, dass Sie das Attribut '{{name}}' entfernen möchten? Alle Benutzer, die derzeit zugewiesen sind, werden abgemeldet.",
|
||||
"delete": "Löschen",
|
||||
"update": "Aktualisieren",
|
||||
"save": "Speichern",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefonnummer wird angegeben",
|
||||
"before_event_trigger": "vor Beginn des Termins",
|
||||
"event_cancelled_trigger": "wenn der Termin abgesagt wird",
|
||||
"after_hosts_cal_video_no_show": "Nachdem Gastgeber nicht zum Cal-Video erscheinen",
|
||||
"after_guests_cal_video_no_show": "Nachdem Gäste nicht zum Cal-Video erscheinen",
|
||||
"after_hosts_cal_video_no_show": "Nachdem die Gastgeber nicht am Cal-Video teilgenommen haben",
|
||||
"after_guests_cal_video_no_show": "Nachdem die Gäste nicht am Cal-Video teilgenommen haben",
|
||||
"new_event_trigger": "wenn ein neuer Termin gebucht wird",
|
||||
"email_host_action": "E-Mail an den Veranstalter senden",
|
||||
"email_attendee_action": "E-Mail an Teilnehmende senden",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Zeiten zur E-Mail hinzufügen",
|
||||
"select_time": "Zeit auswählen",
|
||||
"select_date": "Datum auswählen",
|
||||
"connecting_you_to_someone": "Wir verbinden Sie mit jemandem.",
|
||||
"connecting_you_to_someone": "Wir verbinden Sie mit jemandem von {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Bitte schließen oder aktualisieren Sie diese Seite nicht",
|
||||
"see_all_available_times": "Alle verfügbaren Zeiten ansehen",
|
||||
"org_team_names_example_1": "z.B. Marketing-Team",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Ereignis-Endzeit in der Zeitzone des Teilnehmers",
|
||||
"salesforce_create_event_on_contact": "Event für Kontakt erstellen, falls vorhanden. Andernfalls auf Lead zurückgreifen",
|
||||
"salesforce_owner_name_to_change": "Zu ändernder Besitzername",
|
||||
"dont_have_access_this_page": "Sie haben keinen Zugriff auf diese Seite",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Um diese Seite anzuzeigen oder mit ihr zu interagieren, benötigen Sie Administrator- oder Eigentümerrechte",
|
||||
"field_type": "Feldtyp",
|
||||
"when_to_write": "Wann schreiben",
|
||||
"salesforce_on_booking_write_to_record": "Bei Buchung in ein benutzerdefiniertes Feld des Teilnehmer-{{record}}-Datensatzes schreiben",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Buchungs-Startdatum",
|
||||
"booking_created_date": "Buchungs-Erstellungsdatum",
|
||||
"booking_reassigned_to_host": "Buchung an {{host}} neu zugewiesen",
|
||||
"access_denied": "Zugriff verweigert",
|
||||
"salesforce_route_to_owner": "Der Kontaktinhaber wird der Round Robin Host sein, falls verfügbar",
|
||||
"salesforce_do_not_route_to_owner": "Der Kontaktinhaber wird nicht erzwungen (kann trotzdem Host sein, wenn die Attribute und Round Robin Kriterien übereinstimmen)",
|
||||
"salesforce_route_to_custom_lookup_field": "Weiterleitung an einen Benutzer, der mit einem Lookup-Feld eines Accounts übereinstimmt",
|
||||
"salesforce_option": "Salesforce-Option",
|
||||
"lookup_field_name": "Name des Lookup-Felds",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Fügen Sie Ihre neuen Code-Zeilen über dieser hinzu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Action Required Reschedule: Please book a new time for {{eventType}} with {{name}}",
|
||||
"hi_user_name": "Hi {{name}}",
|
||||
"ics_event_title": "{{eventType}} with {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oops, we couldn't connect you this time. Please schedule a future call instead",
|
||||
"please_book_a_time_sometime_later": "It looks like all of our experts are busy right now. Please schedule a call at a time that works best for you and we'll be ready to assist you.",
|
||||
"schedule_instead": "Schedule instead",
|
||||
"new_event_subject": "New event: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Join by {{entryPoint}}",
|
||||
"notes": "Notes",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Other",
|
||||
"email_sign_in_subject": "Your sign-in link for {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "You are meeting with {{user}}. We sent an email with a calendar invitation with the details to everyone.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} is meeting with {{attendee}}. We sent an email with a calendar invitation with the details to everyone.",
|
||||
"emailed_you_and_attendees": "We sent an email with a calendar invitation with the details to everyone.",
|
||||
"emailed_host_and_attendee": "We sent an email with a calendar invitation with the details to everyone.",
|
||||
"emailed_you_and_attendees_recurring": "We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "You are meeting with {{user}}.We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.",
|
||||
"emailed_host_and_attendee_recurring": "We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "You are meeting with {{user}}. We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} is meeting with {{attendee}}. We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.",
|
||||
"emailed_you_and_any_other_attendees": "We sent an email to everyone with this information.",
|
||||
"needs_to_be_confirmed_or_rejected": "Your booking still needs to be confirmed or rejected.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Your recurring meeting still needs to be confirmed or rejected.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "You don't have any teams yet.",
|
||||
"no_teams_description": "Teams allow others to book events shared between your coworkers.",
|
||||
"submit": "Submit",
|
||||
"confirm_remove_attribute": "Yes, remove attribute",
|
||||
"remove_attribute": "Remove attribute",
|
||||
"remove_attribute_confirmation_message": "Are you sure you want to remove the attribute '{{name}}'? All users currently assigned to it will be unassigned.",
|
||||
"delete": "Delete",
|
||||
"update": "Update",
|
||||
"save": "Save",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Phone number will be provided",
|
||||
"before_event_trigger": "before event starts",
|
||||
"event_cancelled_trigger": "when event is canceled",
|
||||
"after_hosts_cal_video_no_show": "After hosts don't join cal video",
|
||||
"after_guests_cal_video_no_show": "After guests don't join cal video",
|
||||
"after_hosts_cal_video_no_show": "After hosts didn't join cal video",
|
||||
"after_guests_cal_video_no_show": "After guests didn't join cal video",
|
||||
"new_event_trigger": "when new event is booked",
|
||||
"email_host_action": "send email to host",
|
||||
"email_attendee_action": "send email to attendees",
|
||||
@@ -2039,7 +2047,7 @@
|
||||
"looking_for_more_analytics": "Looking for more analytics?",
|
||||
"looking_for_more_insights": "Looking for more Insights?",
|
||||
"filters": "Filters",
|
||||
"add_filter": "Add filter",
|
||||
"add_filter": "Add filter",
|
||||
"add_rule": "Add rule",
|
||||
"add_rule_group": "Add rule group",
|
||||
"remove_filters": "Clear all filters",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Select a few available times and embed them in your Email",
|
||||
"select_time": "Select Time",
|
||||
"select_date": "Select Date",
|
||||
"connecting_you_to_someone": "We are connecting you to someone.",
|
||||
"connecting_you_to_someone": "We are connecting you to someone from {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Please do not close or refresh this page",
|
||||
"see_all_available_times": "See all available times",
|
||||
"org_team_names_example_1": "e.g. Marketing Team",
|
||||
@@ -2746,6 +2754,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Event End Time In Attendee Timezone",
|
||||
"salesforce_create_event_on_contact": "Create event on contact, if it exists. Else fallback to lead",
|
||||
"salesforce_owner_name_to_change": "Owner name to change",
|
||||
"dont_have_access_this_page": "You don't have access to this page",
|
||||
"you_need_admin_or_owner_privileges_to_access": "In order to view or interact with this page, you must have admin or owner privileges",
|
||||
"field_type": "Field type",
|
||||
"when_to_write": "When to write",
|
||||
"salesforce_on_booking_write_to_record": "On booking, write to a custom field on the attendee {{record}} record",
|
||||
@@ -2754,5 +2764,11 @@
|
||||
"booking_start_date": "Booking start date",
|
||||
"booking_created_date": "Booking created date",
|
||||
"booking_reassigned_to_host": "Booking reassigned to {{host}}",
|
||||
"access_denied": "Access Denied",
|
||||
"salesforce_route_to_owner": "Contact owner will be the Round Robin host if available",
|
||||
"salesforce_do_not_route_to_owner": "Contact owner will not be forced (can still be host if it matches the attributes and Round Robin criteria)",
|
||||
"salesforce_route_to_custom_lookup_field": "Route to a user that matches a lookup field on an account",
|
||||
"salesforce_option": "Salesforce Option",
|
||||
"lookup_field_name": "Lookup Field Name",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Acción requerida para reprogramar: Por favor, reserva un nuevo horario para {{eventType}} con {{name}}",
|
||||
"hi_user_name": "Hola {{name}}",
|
||||
"ics_event_title": "{{eventType}} con {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, no pudimos conectarte esta vez. Por favor, programa una llamada futura en su lugar",
|
||||
"please_book_a_time_sometime_later": "Parece que todos nuestros expertos están ocupados en este momento. Por favor, agenda una llamada en el horario que más te convenga y estaremos listos para ayudarte.",
|
||||
"schedule_instead": "Agendar ahora",
|
||||
"new_event_subject": "Nuevo evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Únete por {{entryPoint}}",
|
||||
"notes": "Notas",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Otro",
|
||||
"email_sign_in_subject": "Tu enlace de inicio de sesión para {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Te reunirás con {{user}}. Enviamos un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} se reunirá con {{attendee}}. Enviamos un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"emailed_you_and_attendees": "Enviamos un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"emailed_host_and_attendee": "Enviamos un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"emailed_you_and_attendees_recurring": "Enviamos un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"emailed_host_and_attendee_recurring": "Enviamos un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Te reunirás con {{user}}. Enviamos un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} se reunirá con {{attendee}}. Enviamos un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"emailed_you_and_any_other_attendees": "Enviamos un correo electrónico a todos con esta información.",
|
||||
"needs_to_be_confirmed_or_rejected": "Tu reserva aún necesita ser confirmada o rechazada.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Tu reunión recurrente aún necesita ser confirmada o rechazada.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Aún no tienes equipos.",
|
||||
"no_teams_description": "Los equipos permiten que otros reserven eventos compartidos entre tus compañeros de trabajo.",
|
||||
"submit": "Enviar",
|
||||
"confirm_remove_attribute": "Sí, eliminar atributo",
|
||||
"remove_attribute": "Eliminar atributo",
|
||||
"remove_attribute_confirmation_message": "¿Estás seguro de que deseas eliminar el atributo '{{name}}'? Todos los usuarios asignados actualmente serán desvinculados.",
|
||||
"delete": "Eliminar",
|
||||
"update": "Actualizar",
|
||||
"save": "Guardar",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Se proporcionará el número de teléfono",
|
||||
"before_event_trigger": "antes de que comience el evento",
|
||||
"event_cancelled_trigger": "cuando el evento está cancelado",
|
||||
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unan al video de Cal",
|
||||
"after_guests_cal_video_no_show": "Después de que los invitados no se unan al video de Cal",
|
||||
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unieron a la videollamada",
|
||||
"after_guests_cal_video_no_show": "Después de que los invitados no se unieron a la videollamada",
|
||||
"new_event_trigger": "cuando se reserva un nuevo evento",
|
||||
"email_host_action": "enviar correo electrónico al anfitrión",
|
||||
"email_attendee_action": "enviar correo electrónico a los asistentes",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Selecciona algunos horarios disponibles e insértalos en tu correo electrónico",
|
||||
"select_time": "Seleccionar hora",
|
||||
"select_date": "Seleccionar fecha",
|
||||
"connecting_you_to_someone": "Te estamos conectando con alguien.",
|
||||
"connecting_you_to_someone": "Te estamos conectando con alguien de {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Por favor, no cierres ni actualices esta página",
|
||||
"see_all_available_times": "Ver todos los horarios disponibles",
|
||||
"org_team_names_example_1": "p. ej. Equipo de Marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Hora de finalización del evento en la zona horaria del asistente",
|
||||
"salesforce_create_event_on_contact": "Crear evento en el contacto, si existe. De lo contrario, usar lead como alternativa",
|
||||
"salesforce_owner_name_to_change": "Nombre del propietario a cambiar",
|
||||
"dont_have_access_this_page": "No tienes acceso a esta página",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Para ver o interactuar con esta página, debes tener privilegios de administrador o propietario",
|
||||
"field_type": "Tipo de campo",
|
||||
"when_to_write": "Cuándo escribir",
|
||||
"salesforce_on_booking_write_to_record": "Al reservar, escribir en un campo personalizado en el registro {{record}} del asistente",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Fecha de inicio de la reserva",
|
||||
"booking_created_date": "Fecha de creación de la reserva",
|
||||
"booking_reassigned_to_host": "Reserva reasignada a {{host}}",
|
||||
"access_denied": "Acceso denegado",
|
||||
"salesforce_route_to_owner": "El propietario del contacto será el anfitrión de Round Robin si está disponible",
|
||||
"salesforce_do_not_route_to_owner": "El propietario del contacto no será forzado (aún puede ser anfitrión si coincide con los atributos y criterios de Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Dirigir a un usuario que coincida con un campo de búsqueda en una cuenta",
|
||||
"salesforce_option": "Opción de Salesforce",
|
||||
"lookup_field_name": "Nombre del campo de búsqueda",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agrega tus nuevas cadenas arriba de esta línea ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Reprogramar acción requerida: reserva una nueva hora para {{eventType}} con {{name}}",
|
||||
"hi_user_name": "Hola {{name}}",
|
||||
"ics_event_title": "{{eventType}} con {{name}}",
|
||||
"please_book_a_time_sometime_later": "Vaya, no pudimos conectarte esta vez. Por favor, programa una llamada futura.",
|
||||
"please_book_a_time_sometime_later": "Parece que todos nuestros expertos están ocupados en este momento. Por favor, programa una llamada en el horario que mejor te convenga y estaremos listos para ayudarte.",
|
||||
"schedule_instead": "Programar ahora",
|
||||
"new_event_subject": "Nuevo Evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Únase por {{entryPoint}}",
|
||||
"notes": "Notas",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Otro",
|
||||
"email_sign_in_subject": "Su enlace de inicio de sesión para {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Te reunirás con {{user}}. Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} se reunirá con {{attendee}}. Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"emailed_you_and_attendees": "Le enviamos a usted y a los demás asistentes una invitación al calendario con todos los detalles.",
|
||||
"emailed_host_and_attendee": "Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos.",
|
||||
"emailed_you_and_attendees_recurring": "Le enviamos a usted y a los demás asistentes una invitación al calendario para el primero de estos eventos recurrentes.",
|
||||
"emailed_host_and_attendee_recurring": "Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Te reunirás con {{user}}. Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} se reunirá con {{attendee}}. Hemos enviado un correo electrónico con una invitación de calendario con los detalles a todos para el primero de estos eventos recurrentes.",
|
||||
"emailed_you_and_any_other_attendees": "Usted y cualquier otro asistente han recibido esta información.",
|
||||
"needs_to_be_confirmed_or_rejected": "Su reserva todavía necesita ser confirmada o rechazada.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Su reunión recurrente todavía necesita confirmarse o rechazarse.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Todavía no tienes ningún equipo.",
|
||||
"no_teams_description": "Los equipos permiten que otros reserven eventos compartidos entre tus compañeros de trabajo.",
|
||||
"submit": "Enviar",
|
||||
"confirm_remove_attribute": "Sí, eliminar atributo",
|
||||
"remove_attribute": "Eliminar atributo",
|
||||
"remove_attribute_confirmation_message": "¿Estás seguro de que deseas eliminar el atributo '{{name}}'? Todos los usuarios asignados actualmente serán desvinculados.",
|
||||
"delete": "Eliminar",
|
||||
"update": "Actualizar",
|
||||
"save": "Guardar",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Se proporcionará el número de teléfono",
|
||||
"before_event_trigger": "antes del inicio del evento",
|
||||
"event_cancelled_trigger": "cuando se cancela el evento",
|
||||
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unan al video de Cal",
|
||||
"after_guests_cal_video_no_show": "Después de que los invitados no se unan al video de Cal",
|
||||
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unieron al video de Cal",
|
||||
"after_guests_cal_video_no_show": "Después de que los invitados no se unieron al video de Cal",
|
||||
"new_event_trigger": "cuando se reserva un nuevo evento",
|
||||
"email_host_action": "enviar correo electrónico al anfitrión",
|
||||
"email_attendee_action": "enviar correo electrónico a los asistentes",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Seleccione algunos horarios disponibles e incrústelos en su correo electrónico",
|
||||
"select_time": "Seleccione la hora",
|
||||
"select_date": "Seleccione la fecha",
|
||||
"connecting_you_to_someone": "Te estamos conectando con alguien.",
|
||||
"connecting_you_to_someone": "Te estamos conectando con alguien de {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Por favor, no cierres ni actualices esta página",
|
||||
"see_all_available_times": "Ver todas las horas disponibles",
|
||||
"org_team_names_example_1": "ej. Equipo de marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Hora de finalización del evento en la zona horaria del asistente",
|
||||
"salesforce_create_event_on_contact": "Crear evento en el contacto, si existe. De lo contrario, usar el lead",
|
||||
"salesforce_owner_name_to_change": "Nombre del propietario a cambiar",
|
||||
"dont_have_access_this_page": "No tienes acceso a esta página",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Para ver o interactuar con esta página, debes tener privilegios de administrador o propietario",
|
||||
"field_type": "Tipo de campo",
|
||||
"when_to_write": "Cuándo escribir",
|
||||
"salesforce_on_booking_write_to_record": "Al reservar, escribir en un campo personalizado en el registro {{record}} del asistente",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Fecha de inicio de la reserva",
|
||||
"booking_created_date": "Fecha de creación de la reserva",
|
||||
"booking_reassigned_to_host": "Reserva reasignada a {{host}}",
|
||||
"access_denied": "Acceso denegado",
|
||||
"salesforce_route_to_owner": "El propietario del contacto será el anfitrión de Round Robin si está disponible",
|
||||
"salesforce_do_not_route_to_owner": "No se forzará al propietario del contacto (aún puede ser anfitrión si coincide con los atributos y criterios de Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Dirigir a un usuario que coincida con un campo de búsqueda en una cuenta",
|
||||
"salesforce_option": "Opción de Salesforce",
|
||||
"lookup_field_name": "Nombre del campo de búsqueda",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agregue sus nuevas cadenas arriba ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Nõutud ümberajastamine: Palun broneerige oma {{eventType}} üritusele nimega {{name}} uus aeg",
|
||||
"hi_user_name": "Tere, {{name}}",
|
||||
"ics_event_title": "{{eventType}} koos {{name}}",
|
||||
"please_book_a_time_sometime_later": "Vabandust, meil ei olnud võimalik teiega praegu ühendust luua. Ajastage selle asemel tulevane kõne",
|
||||
"please_book_a_time_sometime_later": "Paistab, et kõik meie eksperdid on hetkel hõivatud. Palun broneeri kõne sulle sobivaks ajaks ja oleme valmis sind aitama.",
|
||||
"schedule_instead": "Broneeri aeg",
|
||||
"new_event_subject": "Uus üritus: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Liituge {{entryPoint}} viisil",
|
||||
"notes": "Märkmed",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Muu",
|
||||
"email_sign_in_subject": "Teie sisselogimislink rakendusele {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Kohtute kasutajaga {{user}}. Saatsime kõigile meili kalendri kutsega koos üksikasjadega.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} kohtub {{attendee}}-ga. Saatsime kõigile e-kirja koos kalendrikutsega, mis sisaldab üksikasju.",
|
||||
"emailed_you_and_attendees": "Saatsime kõigile kalendrikutse üksikasjadega meili.",
|
||||
"emailed_host_and_attendee": "Saatsime kõigile e-kirja koos kalendrikutsega, mis sisaldab üksikasju.",
|
||||
"emailed_you_and_attendees_recurring": "Saatsime kõigile esimeste korduvate sündmuste üksikasjadega meili kalendrikutsega.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Kohtute kasutajaga {{user}}. Saatsime kõigile kalendrikutse koos üksikasjadega meili esimese korduva sündmuse kohta.",
|
||||
"emailed_host_and_attendee_recurring": "Saatsime kõigile e-kirja koos kalendrikutsega, mis sisaldab esimese korduva ürituse üksikasju.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Sa kohtud {{user}}-ga. Saatsime kõigile e-kirja koos kalendrikutsega, mis sisaldab esimese korduva ürituse üksikasju.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} kohtub {{attendee}}-ga. Saatsime kõigile e-kirja koos kalendrikutsega, mis sisaldab esimese korduva ürituse üksikasju.",
|
||||
"emailed_you_and_any_other_attendees": "Saatsime selle teabega kõigile meili.",
|
||||
"needs_to_be_confirmed_or_rejected": "Teie broneering tuleb veel kinnitada või tagasi lükata.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Teie korduv koosolek tuleb veel kinnitada või tagasi lükata.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Teil pole veel ühtegi meeskonda.",
|
||||
"no_teams_description": "Meeskonnad võimaldavad teistel broneerida teie töökaaslaste vahel jagatud sündmusi.",
|
||||
"submit": "Esita",
|
||||
"confirm_remove_attribute": "Jah, eemalda atribuut",
|
||||
"remove_attribute": "Eemalda atribuut",
|
||||
"remove_attribute_confirmation_message": "Kas olete kindel, et soovite atribuudi '{{name}}' eemaldada? Kõik sellele määratud kasutajad eemaldatakse.",
|
||||
"delete": "Kustuta",
|
||||
"update": "Uuendus",
|
||||
"save": "Salvesta",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefoninumber antakse",
|
||||
"before_event_trigger": "enne ürituse algust",
|
||||
"event_cancelled_trigger": "Kui sündmus tühistatakse",
|
||||
"after_hosts_cal_video_no_show": "Pärast seda, kui võõrustajad ei liitu Cal videokõnega",
|
||||
"after_guests_cal_video_no_show": "Pärast seda, kui külalised ei liitu Cal videokõnega",
|
||||
"after_hosts_cal_video_no_show": "Pärast seda, kui võõrustajad ei liitunud cal videoga",
|
||||
"after_guests_cal_video_no_show": "Pärast seda, kui külalised ei liitunud cal videoga",
|
||||
"new_event_trigger": "kui uus sündmus on broneeritud",
|
||||
"email_host_action": "saada e-kiri hostile",
|
||||
"email_attendee_action": "saada osalejatele e-kiri",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Valige mõned vabad ajad ja manustage need oma e-kirja",
|
||||
"select_time": "Vali aeg",
|
||||
"select_date": "Vali kuupäev",
|
||||
"connecting_you_to_someone": "Me ühendame teid kellegagi.",
|
||||
"connecting_you_to_someone": "Me ühendame teid kellegagi {{orgName}}-st.",
|
||||
"please_do_not_close_this_tab": "Palun ärge sulgege ega värskendage seda lehte",
|
||||
"see_all_available_times": "Vaata kõiki saadaolevaid aegu",
|
||||
"org_team_names_example_1": "nt turundusmeeskond",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Sündmuse lõpuaeg osaleja ajavööndis",
|
||||
"salesforce_create_event_on_contact": "Loo sündmus kontaktil, kui see eksisteerib. Vastasel juhul kasuta liidi",
|
||||
"salesforce_owner_name_to_change": "Muudetava omaniku nimi",
|
||||
"dont_have_access_this_page": "Teil ei ole sellele lehele juurdepääsu",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Selle lehe vaatamiseks või sellega suhtlemiseks peate omama administraatori või omaniku õigusi",
|
||||
"field_type": "Välja tüüp",
|
||||
"when_to_write": "Millal kirjutada",
|
||||
"salesforce_on_booking_write_to_record": "Broneeringu korral kirjuta osaleja {{record}} kirje kohandatud väljale",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Broneeringu alguskuupäev",
|
||||
"booking_created_date": "Broneeringu loomise kuupäev",
|
||||
"booking_reassigned_to_host": "Broneering määrati ümber {{host}}-le",
|
||||
"access_denied": "Juurdepääs keelatud",
|
||||
"salesforce_route_to_owner": "Kontakti omanik on round robin host, kui saadaval",
|
||||
"salesforce_do_not_route_to_owner": "Kontakti omanikku ei sunnita (võib siiski olla host, kui vastab atribuutidele ja round robin kriteeriumitele)",
|
||||
"salesforce_route_to_custom_lookup_field": "Suuna kasutajale, kes vastab konto otsinguväljale",
|
||||
"salesforce_option": "Salesforce'i valik",
|
||||
"lookup_field_name": "Otsinguvälja nimi",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Replanification requise : veuillez réserver un nouveau créneau pour {{eventType}} avec {{name}}",
|
||||
"hi_user_name": "Bonjour {{name}}",
|
||||
"ics_event_title": "{{eventType}} avec {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oups, nous n'avons pas pu vous connecter cette fois-ci. Veuillez plutôt planifier un appel ultérieur",
|
||||
"please_book_a_time_sometime_later": "Il semble que tous nos experts soient occupés pour le moment. Veuillez planifier un appel à un moment qui vous convient le mieux et nous serons prêts à vous aider.",
|
||||
"schedule_instead": "Planifier à la place",
|
||||
"new_event_subject": "Nouvel événement : {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Rejoindre par {{entryPoint}}",
|
||||
"notes": "Notes",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Autre",
|
||||
"email_sign_in_subject": "Votre lien de connexion pour {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Vous avez rendez-vous avec {{user}}. Nous avons envoyé un e-mail avec une invitation de calendrier comprenant les détails à tout le monde.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} a un rendez-vous avec {{attendee}}. Nous avons envoyé un e-mail avec une invitation calendrier contenant tous les détails aux participants.",
|
||||
"emailed_you_and_attendees": "Nous avons envoyé un e-mail avec une invitation de calendrier comprenant les détails à tout le monde.",
|
||||
"emailed_host_and_attendee": "Nous avons envoyé un e-mail avec une invitation calendrier contenant tous les détails aux participants.",
|
||||
"emailed_you_and_attendees_recurring": "Nous avons envoyé un e-mail avec une invitation de calendrier comprenant les détails à tout le monde pour le premier de ces événements récurrents.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Vous avez rendez-vous avec {{user}}. Nous avons envoyé un e-mail avec une invitation de calendrier comprenant les détails à tout le monde pour le premier de ces événements récurrents.",
|
||||
"emailed_host_and_attendee_recurring": "Nous avons envoyé un e-mail avec une invitation calendrier contenant tous les détails aux participants pour le premier de ces événements récurrents.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Vous avez un rendez-vous avec {{user}}. Nous avons envoyé un e-mail avec une invitation calendrier contenant tous les détails aux participants pour le premier de ces événements récurrents.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} a un rendez-vous avec {{attendee}}. Nous avons envoyé un e-mail avec une invitation calendrier contenant tous les détails aux participants pour le premier de ces événements récurrents.",
|
||||
"emailed_you_and_any_other_attendees": "Nous avons envoyé cette information à tout le monde par e-mail.",
|
||||
"needs_to_be_confirmed_or_rejected": "Votre réservation doit encore être confirmée ou refusée.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Votre rendez-vous récurrent doit encore être confirmé ou refusé.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Vous n'avez pas encore d'équipe.",
|
||||
"no_teams_description": "Les équipes permettent aux autres de réserver des événements partagés entre vos collègues.",
|
||||
"submit": "Envoyer",
|
||||
"confirm_remove_attribute": "Oui, supprimer l'attribut",
|
||||
"remove_attribute": "Supprimer l'attribut",
|
||||
"remove_attribute_confirmation_message": "Êtes-vous sûr de vouloir supprimer l'attribut '{{name}}' ? Tous les utilisateurs actuellement assignés à cet attribut seront désassignés.",
|
||||
"delete": "Supprimer",
|
||||
"update": "Mettre à jour",
|
||||
"save": "Enregistrer",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Un numéro de téléphone sera fourni",
|
||||
"before_event_trigger": "avant le début de l'événement",
|
||||
"event_cancelled_trigger": "lorsque l'événement est annulé",
|
||||
"after_hosts_cal_video_no_show": "Après que les hôtes ne rejoignent pas la vidéo Cal",
|
||||
"after_guests_cal_video_no_show": "Après que les invités ne rejoignent pas la vidéo Cal",
|
||||
"after_hosts_cal_video_no_show": "Après que les hôtes ne se sont pas connectés à l'appel vidéo",
|
||||
"after_guests_cal_video_no_show": "Après que les invités ne se sont pas connectés à l'appel vidéo",
|
||||
"new_event_trigger": "lorsqu'un nouvel événement est réservé",
|
||||
"email_host_action": "envoyer un e-mail à l'hôte",
|
||||
"email_attendee_action": "envoyer un e-mail aux participants",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Sélectionnez quelques créneaux disponibles et intégrez-les dans votre e-mail.",
|
||||
"select_time": "Sélectionner un créneau",
|
||||
"select_date": "Sélectionner une date",
|
||||
"connecting_you_to_someone": "Nous vous mettons en relation avec quelqu'un.",
|
||||
"connecting_you_to_someone": "Nous vous mettons en relation avec quelqu'un de {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Veuillez ne pas fermer ou actualiser cette page",
|
||||
"see_all_available_times": "Voir tous les créneaux disponibles",
|
||||
"org_team_names_example_1": "p. ex. Équipe marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Heure de fin de l'événement dans le fuseau horaire du participant",
|
||||
"salesforce_create_event_on_contact": "Créer un événement sur le contact, s'il existe. Sinon, utiliser le lead comme alternative",
|
||||
"salesforce_owner_name_to_change": "Nom du propriétaire à modifier",
|
||||
"dont_have_access_this_page": "Vous n'avez pas accès à cette page",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Pour voir ou interagir avec cette page, vous devez avoir des privilèges d'administrateur ou de propriétaire",
|
||||
"field_type": "Type de champ",
|
||||
"when_to_write": "Quand écrire",
|
||||
"salesforce_on_booking_write_to_record": "Lors de la réservation, écrire dans un champ personnalisé sur l'enregistrement {{record}} du participant",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Date de début de la réservation",
|
||||
"booking_created_date": "Date de création de la réservation",
|
||||
"booking_reassigned_to_host": "Réservation réassignée à {{host}}",
|
||||
"access_denied": "Accès refusé",
|
||||
"salesforce_route_to_owner": "Le propriétaire du contact sera l'hôte Round Robin si disponible",
|
||||
"salesforce_do_not_route_to_owner": "Le propriétaire du contact ne sera pas forcé (peut toujours être l'hôte si cela correspond aux attributs et aux critères Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Acheminer vers un utilisateur correspondant à un champ de recherche sur un compte",
|
||||
"salesforce_option": "Option Salesforce",
|
||||
"lookup_field_name": "Nom du champ de recherche",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Ajoutez vos nouvelles chaînes ci-dessus ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "הפעולה חייבה קביעת מועד חדש: יש לקבוע מועד חדש עבור {{eventType}} עם {{name}}",
|
||||
"hi_user_name": "שלום {{name}}",
|
||||
"ics_event_title": "{{eventType}} עם {{name}}",
|
||||
"please_book_a_time_sometime_later": "אף אחד לא זמין כרגע. נא לקבוע זימון למועד אחר",
|
||||
"please_book_a_time_sometime_later": "נראה שכל המומחים שלנו עסוקים כרגע. אנא קבע/י שיחה בזמן שנוח לך ונשמח לסייע לך.",
|
||||
"schedule_instead": "לקבוע במקום",
|
||||
"new_event_subject": "אירוע חדש: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "ניתן להצטרף עד {{entryPoint}}",
|
||||
"notes": "הערות",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "אחר",
|
||||
"email_sign_in_subject": "קישור הכניסה שלך אל {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "נקבעה לך פגישה עם {{user}}. שלחנו לך ולמשתתפים האחרים הודעת דוא״ל עם הזמנה בלוח השנה הכוללת את כל הפרטים.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} נפגש/ת עם {{attendee}}. שלחנו לכולם אימייל עם הזמנה ליומן הכוללת את כל הפרטים.",
|
||||
"emailed_you_and_attendees": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה הכוללת את כל הפרטים.",
|
||||
"emailed_host_and_attendee": "שלחנו לכולם אימייל עם הזמנה ליומן הכוללת את כל הפרטים.",
|
||||
"emailed_you_and_attendees_recurring": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה לאירוע הראשון מבין האירועים החוזרים האלה.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "נקבעה לך פגישה עם {{user}}. שלחנו לך ולמשתתפים האחרים הודעת דוא״ל עם הזמנה בלוח השנה לאירוע הראשון מבין האירועים החוזרים האלה.",
|
||||
"emailed_host_and_attendee_recurring": "שלחנו לכולם אימייל עם הזמנה ליומן הכוללת את הפרטים עבור האירוע הראשון בסדרת האירועים החוזרים.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "את/ה נפגש/ת עם {{user}}. שלחנו לכולם אימייל עם הזמנה ליומן הכוללת את הפרטים עבור האירוע הראשון בסדרת האירועים החוזרים.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} נפגש/ת עם {{attendee}}. שלחנו לכולם אימייל עם הזמנה ליומן הכוללת את הפרטים עבור האירוע הראשון בסדרת האירועים החוזרים.",
|
||||
"emailed_you_and_any_other_attendees": "שלחנו לך ולמשתתפים האחרים, אם ישנם כאלה, הודעת דוא\"ל עם הפרטים האלה.",
|
||||
"needs_to_be_confirmed_or_rejected": "ההזמנה שלך עדיין ממתינה לאישור או לדחייה.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "עדיין לא אישרת/דחית את הפגישה החוזרת.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "עדיין אין לך צוותים.",
|
||||
"no_teams_description": "בעזרת צוותים, אנשים אחרים יכולים לקבוע מועד לאירועים המשותפים לעמיתיך.",
|
||||
"submit": "שליחה",
|
||||
"confirm_remove_attribute": "כן, הסר את המאפיין",
|
||||
"remove_attribute": "הסר מאפיין",
|
||||
"remove_attribute_confirmation_message": "האם אתה בטוח שברצונך להסיר את המאפיין '{{name}}'? כל המשתמשים המוקצים לו יוסרו.",
|
||||
"delete": "מחיקה",
|
||||
"update": "עדכון",
|
||||
"save": "שמירה",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "מספר הטלפון יסופק",
|
||||
"before_event_trigger": "לפני שהאירוע מתחיל",
|
||||
"event_cancelled_trigger": "כאשר אירוע מבוטל",
|
||||
"after_hosts_cal_video_no_show": "לאחר שהמארחים לא מצטרפים לשיחת הווידאו ב-Cal",
|
||||
"after_guests_cal_video_no_show": "לאחר שהאורחים לא מצטרפים לשיחת הווידאו ב-Cal",
|
||||
"after_hosts_cal_video_no_show": "לאחר שהמארחים לא הצטרפו לשיחת הוידאו",
|
||||
"after_guests_cal_video_no_show": "לאחר שהאורחים לא הצטרפו לשיחת הוידאו",
|
||||
"new_event_trigger": "כאשר אירוע חדש מוזמן",
|
||||
"email_host_action": "שלח מייל למארח",
|
||||
"email_attendee_action": "שליחת דוא\"ל למשתתפים",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "בחר/י כמה מועדים פנויים והטבע/י אותם בדוא\"ל",
|
||||
"select_time": "בחירת שעה",
|
||||
"select_date": "בחירת תאריך",
|
||||
"connecting_you_to_someone": "אנו מחברים אותך למישהו או מישהי.",
|
||||
"connecting_you_to_someone": "אנו מחברים אותך למישהו מ-{{orgName}}.",
|
||||
"please_do_not_close_this_tab": "אנא אל תסגור או תרענן דף זה",
|
||||
"see_all_available_times": "לצפייה בכל המועדים הפנויים",
|
||||
"org_team_names_example_1": "לדוגמה, מחלקת שיווק",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "זמן סיום האירוע באזור הזמן של המשתתף",
|
||||
"salesforce_create_event_on_contact": "צור אירוע על איש קשר, אם קיים. אחרת, חזור ללידים",
|
||||
"salesforce_owner_name_to_change": "שם הבעלים לשינוי",
|
||||
"dont_have_access_this_page": "אין לך גישה לדף זה",
|
||||
"you_need_admin_or_owner_privileges_to_access": "כדי לצפות או לפעול בדף זה, עליך להיות בעל הרשאות מנהל או בעלים",
|
||||
"field_type": "סוג שדה",
|
||||
"when_to_write": "מתי לכתוב",
|
||||
"salesforce_on_booking_write_to_record": "בעת הזמנה, כתוב לשדה מותאם אישית ברשומת המשתתף {{record}}",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "תאריך תחילת ההזמנה",
|
||||
"booking_created_date": "תאריך יצירת ההזמנה",
|
||||
"booking_reassigned_to_host": "ההזמנה הועברה למארח {{host}}",
|
||||
"access_denied": "הגישה נדחתה",
|
||||
"salesforce_route_to_owner": "בעל איש הקשר יהיה מארח ה-Round Robin אם זמין",
|
||||
"salesforce_do_not_route_to_owner": "בעל איש הקשר לא יהיה מאולץ (עדיין יכול להיות מארח אם תואם את המאפיינים וקריטריוני ה-Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "נתב למשתמש התואם לשדה חיפוש בחשבון",
|
||||
"salesforce_option": "אפשרות Salesforce",
|
||||
"lookup_field_name": "שם שדה החיפוש",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Átütmezés szükséges: Kérlek foglalj új időpontot a következőre: {{eventType}}, {{name}}",
|
||||
"hi_user_name": "Szia {{name}}",
|
||||
"ics_event_title": "{{eventType}} a következővel: {{name}}",
|
||||
"please_book_a_time_sometime_later": "Hoppá, ezúttal nem tudtuk összekapcsolni. Kérjük, ütemezzen be egy jövőbeli hívást",
|
||||
"please_book_a_time_sometime_later": "Úgy tűnik, hogy szakértőink jelenleg mind elfoglaltak. Kérjük, foglaljon időpontot egy önnek megfelelő időpontra, és készséggel állunk majd rendelkezésére.",
|
||||
"schedule_instead": "Időpontfoglalás",
|
||||
"new_event_subject": "Új esemény: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Csatlakozás a következővel: {{entryPoint}}",
|
||||
"notes": "Jegyzetek",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Egyéb",
|
||||
"email_sign_in_subject": "Bejelentkezési link a következőhöz: {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Találkotó a következővel: {{user}}. Mindenkinek küldtünk egy naptári meghívót a részletekkel.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} találkozik {{attendee}} résztvevővel. Mindenkinek küldtünk egy e-mailt a naptári meghívóval és a részletekkel.",
|
||||
"emailed_you_and_attendees": "Mindenkinek küldtünk egy e-mailt a naptár meghívóval és a részletekkel.",
|
||||
"emailed_host_and_attendee": "Mindenkinek küldtünk egy e-mailt a naptári meghívóval és a részletekkel.",
|
||||
"emailed_you_and_attendees_recurring": "Mindenkinek küldtünk e-mailben egy naptár meghívót a részletekkel az első ismétlődő eseményről.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Találkozó a következővel: {{user}}. E-mailben küldtünk egy naptári meghívót mindenkinek az első ismétlődő esemény részleteivel.",
|
||||
"emailed_host_and_attendee_recurring": "Mindenkinek küldtünk egy e-mailt a naptári meghívóval és a részletekkel az ismétlődő események első alkalmára.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Ön találkozik {{user}} résztvevővel. Mindenkinek küldtünk egy e-mailt a naptári meghívóval és a részletekkel az ismétlődő események első alkalmára.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} találkozik {{attendee}} résztvevővel. Mindenkinek küldtünk egy e-mailt a naptári meghívóval és a részletekkel az ismétlődő események első alkalmára.",
|
||||
"emailed_you_and_any_other_attendees": "Küldtünk egy e-mail-t mindenkinek ezekről az információkról.",
|
||||
"needs_to_be_confirmed_or_rejected": "Foglalását még meg kell erősíteni vagy el kell utasítani.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Az ismétlődő találkozót még meg kell erősíteni vagy el kell utasítani.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Még nincs csapatod.",
|
||||
"no_teams_description": "A csapatok lehetővé teszik mások számára, hogy lefoglalják a munkatársai között megosztott eseményeket.",
|
||||
"submit": "Beküldés",
|
||||
"confirm_remove_attribute": "Igen, az attribútum eltávolítása",
|
||||
"remove_attribute": "Attribútum eltávolítása",
|
||||
"remove_attribute_confirmation_message": "Biztosan el szeretné távolítani a(z) '{{name}}' attribútumot? Minden jelenleg hozzárendelt felhasználó hozzárendelése megszűnik.",
|
||||
"delete": "Törlés",
|
||||
"update": "Frissítés",
|
||||
"save": "Mentés",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "A telefonszámot megadjuk",
|
||||
"before_event_trigger": "az esemény kezdete előtt",
|
||||
"event_cancelled_trigger": "amikor az esemény le lett mondva",
|
||||
"after_hosts_cal_video_no_show": "Miután a házigazdák nem csatlakoznak a cal videóhoz",
|
||||
"after_guests_cal_video_no_show": "Miután a vendégek nem csatlakoznak a cal videóhoz",
|
||||
"after_hosts_cal_video_no_show": "Miután a házigazdák nem csatlakoztak a Cal videóhoz",
|
||||
"after_guests_cal_video_no_show": "Miután a vendégek nem csatlakoztak a Cal videóhoz",
|
||||
"new_event_trigger": "új esemény lefoglalásakor",
|
||||
"email_host_action": "küldjön e-mailt a házigazdának",
|
||||
"email_attendee_action": "küldjön e-mailt a résztvevőknek",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Válasszon ki néhány elérhető időpontot, és ágyazza be e-mailjeibe",
|
||||
"select_time": "Válasszon időt",
|
||||
"select_date": "Válasszon dátumot",
|
||||
"connecting_you_to_someone": "Összekapcsolunk valakivel.",
|
||||
"connecting_you_to_someone": "Kapcsolatba hozzuk egy {{orgName}} munkatársával.",
|
||||
"please_do_not_close_this_tab": "Kérjük, ne zárja be vagy frissítse ezt az oldalt",
|
||||
"see_all_available_times": "Az összes elérhető időpont megtekintése",
|
||||
"org_team_names_example_1": "például. Marketing Csapat",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Esemény befejezési ideje a résztvevő időzónájában",
|
||||
"salesforce_create_event_on_contact": "Esemény létrehozása a kapcsolaton, ha létezik. Egyébként visszalépés a leadre",
|
||||
"salesforce_owner_name_to_change": "Módosítandó tulajdonos neve",
|
||||
"dont_have_access_this_page": "Nincs hozzáférése ehhez az oldalhoz",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Az oldal megtekintéséhez vagy használatához adminisztrátori vagy tulajdonosi jogosultság szükséges",
|
||||
"field_type": "Mező típusa",
|
||||
"when_to_write": "Mikor írjon",
|
||||
"salesforce_on_booking_write_to_record": "Foglaláskor írjon egy egyéni mezőbe a résztvevő {{record}} rekordjában",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Foglalás kezdő dátuma",
|
||||
"booking_created_date": "Foglalás létrehozásának dátuma",
|
||||
"booking_reassigned_to_host": "Foglalás átirányítva a következő házigazdához: {{host}}",
|
||||
"access_denied": "Hozzáférés megtagadva",
|
||||
"salesforce_route_to_owner": "A kapcsolattartó tulajdonosa lesz a round robin házigazda, ha elérhető",
|
||||
"salesforce_do_not_route_to_owner": "A kapcsolattartó tulajdonosa nem lesz kötelező (továbbra is lehet házigazda, ha megfelel a tulajdonságoknak és a round robin kritériumoknak)",
|
||||
"salesforce_route_to_custom_lookup_field": "Átirányítás olyan felhasználóhoz, aki megfelel a fiók keresési mezőjének",
|
||||
"salesforce_option": "Salesforce beállítás",
|
||||
"lookup_field_name": "Keresési mező neve",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adja hozzá az új karakterláncokat fent ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Azione richiesta per la riprogrammazione: prenota un nuovo orario per {{eventType}} con {{name}}",
|
||||
"hi_user_name": "Ciao {{name}}",
|
||||
"ics_event_title": "{{eventType}} con {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oops, non siamo riusciti a collegarti. Pianifica una chiamata futura",
|
||||
"please_book_a_time_sometime_later": "Sembra che tutti i nostri esperti siano occupati al momento. Ti invitiamo a programmare una chiamata in un momento che ti sia più comodo e saremo pronti ad assisterti.",
|
||||
"schedule_instead": "Programma invece",
|
||||
"new_event_subject": "Richiesta di nuovo evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Entra da {{entryPoint}}",
|
||||
"notes": "Osservazioni",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Altro",
|
||||
"email_sign_in_subject": "Link di accesso a {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Avrai un incontro con {{user}}. Abbiamo inviato a tutti un'email di invito contenente tutte le informazioni.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} si incontra con {{attendee}}. Abbiamo inviato un'email con un invito al calendario con i dettagli a tutti.",
|
||||
"emailed_you_and_attendees": "Abbiamo inviato via email a te e agli altri partecipanti un invito al calendario con tutti i dettagli.",
|
||||
"emailed_host_and_attendee": "Abbiamo inviato un'email con un invito al calendario con i dettagli a tutti.",
|
||||
"emailed_you_and_attendees_recurring": "Abbiamo inviato via email a te e agli altri partecipanti un invito al primo di questi eventi ricorrenti.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Avrai un incontro con {{user}}. Abbiamo inviato a tutti un'email di invito contenente tutte le informazioni per il primo di questi eventi ricorrenti.",
|
||||
"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.",
|
||||
"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.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Non hai ancora alcun team.",
|
||||
"no_teams_description": "I team permettono ad altri di prenotare eventi in condivisione con i tuoi collaboratori.",
|
||||
"submit": "Invia",
|
||||
"confirm_remove_attribute": "Sì, rimuovi attributo",
|
||||
"remove_attribute": "Rimuovi attributo",
|
||||
"remove_attribute_confirmation_message": "Sei sicuro di voler rimuovere l'attributo '{{name}}'? Tutti gli utenti attualmente assegnati verranno disassegnati.",
|
||||
"delete": "Elimina",
|
||||
"update": "Aggiorna",
|
||||
"save": "Salva",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Verrà fornito il numero di telefono",
|
||||
"before_event_trigger": "prima dell'inizio dell'evento",
|
||||
"event_cancelled_trigger": "quando l'evento viene cancellato",
|
||||
"after_hosts_cal_video_no_show": "Dopo che gli host non si uniscono al video di Cal",
|
||||
"after_guests_cal_video_no_show": "Dopo che gli ospiti non si uniscono al video di Cal",
|
||||
"after_hosts_cal_video_no_show": "Dopo che gli host non si sono uniti alla videochiamata",
|
||||
"after_guests_cal_video_no_show": "Dopo che gli ospiti non si sono uniti alla videochiamata",
|
||||
"new_event_trigger": "quando viene prenotato un nuovo evento",
|
||||
"email_host_action": "invia e-mail all'organizzatore",
|
||||
"email_attendee_action": "invia e-mail ai partecipanti",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Seleziona alcuni orari disponibili e incorporali nella tua e-mail",
|
||||
"select_time": "Seleziona l'ora",
|
||||
"select_date": "Seleziona la data",
|
||||
"connecting_you_to_someone": "Ti stiamo collegando con qualcuno.",
|
||||
"connecting_you_to_someone": "Ti stiamo mettendo in contatto con qualcuno di {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Per favore, non chiudere o aggiornare questa pagina",
|
||||
"see_all_available_times": "Vedi tutti gli orari disponibili",
|
||||
"org_team_names_example_1": "ad es., team di marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Ora di fine evento nel fuso orario del partecipante",
|
||||
"salesforce_create_event_on_contact": "Crea evento sul contatto, se esiste. Altrimenti, passa al lead",
|
||||
"salesforce_owner_name_to_change": "Nome del proprietario da modificare",
|
||||
"dont_have_access_this_page": "Non hai accesso a questa pagina",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Per visualizzare o interagire con questa pagina, devi avere privilegi di amministratore o proprietario",
|
||||
"field_type": "Tipo di campo",
|
||||
"when_to_write": "Quando scrivere",
|
||||
"salesforce_on_booking_write_to_record": "Al momento della prenotazione, scrivi in un campo personalizzato nel record {{record}} del partecipante",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Data di inizio prenotazione",
|
||||
"booking_created_date": "Data di creazione della prenotazione",
|
||||
"booking_reassigned_to_host": "Prenotazione riassegnata a {{host}}",
|
||||
"access_denied": "Accesso negato",
|
||||
"salesforce_route_to_owner": "Il proprietario del contatto sarà l'host del Round Robin se disponibile",
|
||||
"salesforce_do_not_route_to_owner": "Il proprietario del contatto non sarà obbligato (può comunque essere l'host se corrisponde agli attributi e ai criteri del Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Instrada a un utente che corrisponde a un campo di ricerca su un account",
|
||||
"salesforce_option": "Opzione Salesforce",
|
||||
"lookup_field_name": "Nome del campo di ricerca",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Aggiungi le tue nuove stringhe qui sopra ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "スケジュール変更のアクションが必要です: {{name}} との {{eventType}} に新しい時間を予約してください",
|
||||
"hi_user_name": "こんにちは、{{name}} さん",
|
||||
"ics_event_title": "{{name}} との {{eventType}}",
|
||||
"please_book_a_time_sometime_later": "おっと、今回は接続できませんでした。後で再度スケジュールしてください。",
|
||||
"please_book_a_time_sometime_later": "現在、すべての専門家が対応中のようです。ご都合の良い時間にお電話を予約していただければ、準備してお待ちしております。",
|
||||
"schedule_instead": "代わりに予約する",
|
||||
"new_event_subject": "新規イベント: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "{{entryPoint}} に参加する",
|
||||
"notes": "メモ",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "その他",
|
||||
"email_sign_in_subject": "{{appName}} のサインインリンク",
|
||||
"round_robin_emailed_you_and_attendees": "{{user}}とのミーティングが設定されました。詳細を含むカレンダー招待を全員にメールで送信しました。",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}}が{{attendee}}と面談予定です。詳細を含む予定表の招待メールを全員に送信しました。",
|
||||
"emailed_you_and_attendees": "あなたと他の出席者にすべての詳細を記載したカレンダーの招待状を電子メールで送信しました。",
|
||||
"emailed_host_and_attendee": "詳細を含む予定表の招待メールを全員に送信しました。",
|
||||
"emailed_you_and_attendees_recurring": "あなたと他の出席者にこの繰り返しイベント初回のカレンダーの招待状を電子メールで送信しました。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}}との定期的なミーティングが設定されました。最初のイベントの詳細を含むカレンダー招待を全員にメールで送信しました。",
|
||||
"emailed_host_and_attendee_recurring": "定期的な予定の最初の回について、詳細を含む予定表の招待メールを全員に送信しました。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "あなたは{{user}}と面談予定です。定期的な予定の最初の回について、詳細を含む予定表の招待メールを全員に送信しました。",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}}が{{attendee}}と面談予定です。定期的な予定の最初の回について、詳細を含む予定表の招待メールを全員に送信しました。",
|
||||
"emailed_you_and_any_other_attendees": "あなたと他の参加者にこの情報を電子メールで送信しました。",
|
||||
"needs_to_be_confirmed_or_rejected": "予約は依然として確認または拒否が必要です。",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "繰り返しミーティングは、まだ確認または拒否が必要です。",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "まだチームがありません。",
|
||||
"no_teams_description": "チームを使用することにより、同僚の間で共有されているイベントを予約できるようになります。",
|
||||
"submit": "送信",
|
||||
"confirm_remove_attribute": "はい、属性を削除します",
|
||||
"remove_attribute": "属性を削除",
|
||||
"remove_attribute_confirmation_message": "属性「{{name}}」を削除してもよろしいですか?現在この属性が割り当てられているすべてのユーザーの割り当てが解除されます。",
|
||||
"delete": "削除",
|
||||
"update": "更新",
|
||||
"save": "保存",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "電話番号が提供されます",
|
||||
"before_event_trigger": "イベント開始前に",
|
||||
"event_cancelled_trigger": "イベントキャンセル時",
|
||||
"after_hosts_cal_video_no_show": "ホストがCalビデオに参加しない場合",
|
||||
"after_guests_cal_video_no_show": "ゲストがCalビデオに参加しない場合",
|
||||
"after_hosts_cal_video_no_show": "ホストがCalビデオに参加しなかった後",
|
||||
"after_guests_cal_video_no_show": "ゲストがCalビデオに参加しなかった後",
|
||||
"new_event_trigger": "新しいイベント予約時に",
|
||||
"email_host_action": "ホストにメールを送信",
|
||||
"email_attendee_action": "出席者にメールを送る",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "出席できる時間帯をいくつか選んで、メールに埋め込みます",
|
||||
"select_time": "時間帯を選ぶ",
|
||||
"select_date": "日付を選ぶ",
|
||||
"connecting_you_to_someone": "誰かに接続しています。",
|
||||
"connecting_you_to_someone": "{{orgName}}の担当者におつなぎしています。",
|
||||
"please_do_not_close_this_tab": "このページを閉じたり、リフレッシュしたりしないでください",
|
||||
"see_all_available_times": "出席できる時間帯をすべて表示",
|
||||
"org_team_names_example_1": "例:マーケティングチーム",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "参加者のタイムゾーンでのイベント終了時間",
|
||||
"salesforce_create_event_on_contact": "連絡先が存在する場合はイベントを作成し、存在しない場合はリードにフォールバック",
|
||||
"salesforce_owner_name_to_change": "変更する所有者名",
|
||||
"dont_have_access_this_page": "このページにアクセスする権限がありません",
|
||||
"you_need_admin_or_owner_privileges_to_access": "このページを表示または操作するには、管理者または所有者の権限が必要です",
|
||||
"field_type": "フィールドタイプ",
|
||||
"when_to_write": "書き込むタイミング",
|
||||
"salesforce_on_booking_write_to_record": "予約時、参加者の{{record}}レコードのカスタムフィールドに書き込む",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "予約開始日",
|
||||
"booking_created_date": "予約作成日",
|
||||
"booking_reassigned_to_host": "予約が{{host}}に再割り当てされました",
|
||||
"access_denied": "アクセスが拒否されました",
|
||||
"salesforce_route_to_owner": "可能な場合、取引先責任者の所有者がラウンドロビンのホストになります",
|
||||
"salesforce_do_not_route_to_owner": "取引先責任者の所有者は強制されません(属性とラウンドロビンの基準に一致する場合はホストになる可能性があります)",
|
||||
"salesforce_route_to_custom_lookup_field": "取引先の参照項目に一致するユーザーに割り当てる",
|
||||
"salesforce_option": "Salesforceオプション",
|
||||
"lookup_field_name": "参照項目名",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ この上に新しい文字列を追加してください ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "ត្រូវតែកាលវិភាគឡើងវិញ: សូមកក់ពេលវេលាថ្មីសម្រាប់ {{eventType}} ជាមួយ {{name}}",
|
||||
"hi_user_name": "សួស្តី {{name}}",
|
||||
"ics_event_title": "{{eventType}} ជាមួយ {{name}}",
|
||||
"please_book_a_time_sometime_later": "សូមទោស យើងមិនអាចភ្ជាប់អ្នកបាននៅពេលនេះទេ។ សូមកំណត់ពេលហៅម្តងទៀត។",
|
||||
"please_book_a_time_sometime_later": "មើលទៅអ្នកជំនាញរបស់យើងទាំងអស់កំពុងជាប់រវល់នៅពេលនេះ។ សូមកំណត់ពេលវេលាហៅទូរស័ព្ទនៅពេលដែលងាយស្រួលសម្រាប់អ្នក ហើយយើងនឹងត្រៀមខ្លួនជាស្រេចដើម្បីជួយអ្នក។",
|
||||
"schedule_instead": "កំណត់ពេលវេលាជំនួសវិញ",
|
||||
"new_event_subject": "ព្រឹត្តិការណ៍ថ្មី៖ {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "ចូលរួមដោយ {{entryPoint}}",
|
||||
"notes": "កំណត់ចំណាំ",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "ផ្សេងទៀត",
|
||||
"email_sign_in_subject": "តំណភ្ជាប់ចូលរបស់អ្នកសម្រាប់ {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "អ្នកកំពុងជួបជាមួយ {{user}}។ យើងបានផ្ញើអ៊ីមែលជាមួយការអញ្ជើញប្រតិទិនដែលមានព័ត៌មានលម្អិតទៅកាន់គ្រប់គ្នា។",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} កំពុងជួបជាមួយ {{attendee}}។ យើងបានផ្ញើអ៊ីមែលដែលមានការអញ្ជើញកាលវិភាគជាមួយព័ត៌មានទៅអ្នកទាំងអស់គ្នា។",
|
||||
"emailed_you_and_attendees": "យើងបានផ្ញើអ៊ីមែលជាមួយការអញ្ជើញប្រតិទិនដែលមានព័ត៌មានលម្អិតទៅកាន់គ្រប់គ្នា។",
|
||||
"emailed_host_and_attendee": "យើងបានផ្ញើអ៊ីមែលដែលមានការអញ្ជើញកាលវិភាគជាមួយព័ត៌មានទៅអ្នកទាំងអស់គ្នា។",
|
||||
"emailed_you_and_attendees_recurring": "យើងបានផ្ញើអ៊ីមែលជាមួយការអញ្ជើញប្រតិទិនដែលមានព័ត៌មានលម្អិតទៅកាន់គ្រប់គ្នាសម្រាប់ព្រឹត្តិការណ៍ដែលកើតឡើងជាថេរនេះ។",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "អ្នកកំពុងជួបជាមួយ {{user}}។ យើងបានផ្ញើអ៊ីមែលជាមួយការអញ្ជើញប្រតិទិនដែលមានព័ត៌មានលម្អិតទៅកាន់គ្រប់គ្នាសម្រាប់ព្រឹត្តិការណ៍ដែលកើតឡើងជាថេរនេះ។",
|
||||
"emailed_host_and_attendee_recurring": "យើងបានផ្ញើអ៊ីមែលដែលមានការអញ្ជើញកាលវិភាគជាមួយព័ត៌មានទៅអ្នកទាំងអស់គ្នាសម្រាប់ព្រឹត្តិការណ៍ជាប្រចាំដំបូងនេះ។",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "អ្នកកំពុងជួបជាមួយ {{user}}។ យើងបានផ្ញើអ៊ីមែលដែលមានការអញ្ជើញកាលវិភាគជាមួយព័ត៌មានទៅអ្នកទាំងអស់គ្នាសម្រាប់ព្រឹត្តិការណ៍ជាប្រចាំដំបូងនេះ។",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} កំពុងជួបជាមួយ {{attendee}}។ យើងបានផ្ញើអ៊ីមែលដែលមានការអញ្ជើញកាលវិភាគជាមួយព័ត៌មានទៅអ្នកទាំងអស់គ្នាសម្រាប់ព្រឹត្តិការណ៍ជាប្រចាំដំបូងនេះ។",
|
||||
"emailed_you_and_any_other_attendees": "យើងបានផ្ញើអ៊ីមែលទៅកាន់គ្រប់គ្នាជាមួយព័ត៌មាននេះ។",
|
||||
"needs_to_be_confirmed_or_rejected": "ការកក់របស់អ្នកត្រូវការការបញ្ជាក់ឬបដិសេធ។",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "ការជួបជុំជាថេររបស់អ្នកត្រូវការការបញ្ជាក់ឬបដិសេធ។",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "អ្នកមិនមានក្រុមណាមួយនៅឡើយទេ។",
|
||||
"no_teams_description": "ក្រុមអនុញ្ញាតឱ្យអ្នកដទៃកក់ព្រឹត្តិការណ៍ដែលចែករំលែករវាងមិត្តរួមការងាររបស់អ្នក។",
|
||||
"submit": "ដាក់ស្នើ",
|
||||
"confirm_remove_attribute": "បាទ/ចាស, លុបគុណលក្ខណៈ",
|
||||
"remove_attribute": "លុបគុណលក្ខណៈ",
|
||||
"remove_attribute_confirmation_message": "តើអ្នកប្រាកដថាចង់លុបគុណលក្ខណៈ '{{name}}' មែនទេ? អ្នកប្រើប្រាស់ទាំងអស់ដែលបានផ្ដល់ឱ្យវានឹងត្រូវបានដកចេញ។",
|
||||
"delete": "លុប",
|
||||
"update": "ធ្វើបច្ចុប្បន្នភាព",
|
||||
"save": "រក្សាទុក",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "លេខទូរស័ព្ទនឹងត្រូវបានផ្តល់",
|
||||
"before_event_trigger": "មុនព្រឹត្តិការណ៍ចាប់ផ្តើម",
|
||||
"event_cancelled_trigger": "ពេលព្រឹត្តិការណ៍ត្រូវបានលុបចោល",
|
||||
"after_hosts_cal_video_no_show": "បន្ទាប់ពីម្ចាស់ផ្ទះមិនចូលរួមវីដេអូ cal",
|
||||
"after_guests_cal_video_no_show": "បន្ទាប់ពីភ្ញៀវមិនចូលរួមវីដេអូ cal",
|
||||
"after_hosts_cal_video_no_show": "បន្ទាប់ពីម្ចាស់ផ្ទះមិនបានចូលរួមក្នុងវីដេអូ Cal",
|
||||
"after_guests_cal_video_no_show": "បន្ទាប់ពីភ្ញៀវមិនបានចូលរួមក្នុងវីដេអូ Cal",
|
||||
"new_event_trigger": "ពេលមានការកក់ព្រឹត្តិការណ៍ថ្មី",
|
||||
"email_host_action": "ផ្ញើអ៊ីមែលទៅម្ចាស់",
|
||||
"email_attendee_action": "ផ្ញើអ៊ីមែលទៅអ្នកចូលរួម",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "ជ្រើសរើសពេលវេលាដែលអាចប្រើបានប៉ុន្មាន និងបញ្ចូលវានៅក្នុងអ៊ីមែលរបស់អ្នក",
|
||||
"select_time": "ជ្រើសរើសពេលវេលា",
|
||||
"select_date": "ជ្រើសរើសកាលបរិច្ឆេទ",
|
||||
"connecting_you_to_someone": "យើងកំពុងភ្ជាប់អ្នកទៅនរណាម្នាក់។",
|
||||
"connecting_you_to_someone": "យើងកំពុងភ្ជាប់អ្នកទៅនរណាម្នាក់ពី {{orgName}}។",
|
||||
"please_do_not_close_this_tab": "សូមកុំបិទ ឬធ្វើការបន្ទាន់សម័យទំព័រនេះ",
|
||||
"see_all_available_times": "មើលពេលវេលាទាំងអស់ដែលអាចប្រើបាន",
|
||||
"org_team_names_example_1": "ឧ. ក្រុមទីផ្សារ",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "ពេលវេលាបញ្ចប់ព្រឹត្តិការណ៍នៅក្នុងតំបន់ពេលវេលារបស់អ្នកចូលរួម",
|
||||
"salesforce_create_event_on_contact": "បង្កើតព្រឹត្តិការណ៍នៅលើទំនាក់ទំនង បើមាន។ បើមិនដូច្នោះទេ ត្រឡប់ទៅ lead វិញ",
|
||||
"salesforce_owner_name_to_change": "ឈ្មោះម្ចាស់ដែលត្រូវផ្លាស់ប្តូរ",
|
||||
"dont_have_access_this_page": "អ្នកមិនមានសិទ្ធិចូលប្រើទំព័រនេះទេ",
|
||||
"you_need_admin_or_owner_privileges_to_access": "ដើម្បីមើល ឬប្រើប្រាស់ទំព័រនេះ អ្នកត្រូវតែមានសិទ្ធិជាអ្នកគ្រប់គ្រង ឬម្ចាស់",
|
||||
"field_type": "ប្រភេទវាល",
|
||||
"when_to_write": "ពេលណាត្រូវសរសេរ",
|
||||
"salesforce_on_booking_write_to_record": "នៅពេលកក់ សរសេរទៅវាលផ្ទាល់ខ្លួននៅលើកំណត់ត្រា {{record}} របស់អ្នកចូលរួម",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "កាលបរិច្ឆេទចាប់ផ្តើមការកក់",
|
||||
"booking_created_date": "កាលបរិច្ឆេទបង្កើតការកក់",
|
||||
"booking_reassigned_to_host": "ការកក់ត្រូវបានកំណត់ឡើងវិញទៅ {{host}}",
|
||||
"access_denied": "ការចូលប្រើត្រូវបានបដិសេធ",
|
||||
"salesforce_route_to_owner": "ម្ចាស់ទំនាក់ទំនងនឹងជាម្ចាស់ Round Robin ប្រសិនបើមានស្រាប់។",
|
||||
"salesforce_do_not_route_to_owner": "ម្ចាស់ទំនាក់ទំនងនឹងមិនត្រូវបានបង្ខំ (អាចនៅតែជាម្ចាស់ប្រសិនបើវាដូចគ្នាជាមួយលក្ខណៈ និងលក្ខខណ្ឌ Round Robin)។",
|
||||
"salesforce_route_to_custom_lookup_field": "ផ្លូវទៅកាន់អ្នកប្រើដែលត្រូវនឹងវាលស្វែងរកនៅលើគណនី។",
|
||||
"salesforce_option": "ជម្រើស Salesforce",
|
||||
"lookup_field_name": "ឈ្មោះវាលស្វែងរក",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ បន្ថែមខ្សែអក្សរថ្មីរបស់អ្នកនៅខាងលើនេះ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "일정 변경 조치 필요: {{name}} 님과 함께 새로운 {{eventType}} 시간을 예약하십시오",
|
||||
"hi_user_name": "안녕하세요 {{name}}",
|
||||
"ics_event_title": "{{eventType}}과 {{name}}",
|
||||
"please_book_a_time_sometime_later": "죄송합니다, 이번에는 연결할 수 없었습니다. 나중에 다시 예약해 주세요.",
|
||||
"please_book_a_time_sometime_later": "현재 모든 전문가가 바쁘신 것 같습니다. 귀하에게 가장 적합한 시간에 전화를 예약해 주시면 저희가 도와드리겠습니다.",
|
||||
"schedule_instead": "대신 예약하기",
|
||||
"new_event_subject": "새 이벤트: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "{{entryPoint}}로 가입하세요",
|
||||
"notes": "노트",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "더 보기",
|
||||
"email_sign_in_subject": "{{appName}}의 로그인 링크",
|
||||
"round_robin_emailed_you_and_attendees": "{{user}}와의 미팅이 예정되어 있습니다. 모든 참석자에게 캘린더 초대 이메일을 보냈습니다.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}}님이 {{attendee}}님과 만납니다. 모든 사람에게 세부 사항이 포함된 캘린더 초대 이메일을 보냈습니다.",
|
||||
"emailed_you_and_attendees": "당신과 다른 참여자들에게 상세 사항이 담긴 캘린더 초대 이메일을 보냈습니다.",
|
||||
"emailed_host_and_attendee": "모든 사람에게 세부 사항이 포함된 캘린더 초대 이메일을 보냈습니다.",
|
||||
"emailed_you_and_attendees_recurring": "귀하와 다른 참석자들에게 이 되풀이 이벤트의 첫 이벤트에 대한 예약 초대장을 이메일로 발송했습니다.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}}와의 미팅이 예정되어 있습니다. 반복되는 이벤트의 첫 번째 일정에 대한 캘린더 초대 이메일을 모든 참석자에게 보냈습니다.",
|
||||
"emailed_host_and_attendee_recurring": "반복되는 이벤트 중 첫 번째에 대한 세부 사항이 포함된 캘린더 초대 이메일을 모든 사람에게 보냈습니다.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}}님과 만납니다. 반복되는 이벤트 중 첫 번째에 대한 세부 사항이 포함된 캘린더 초대 이메일을 모든 사람에게 보냈습니다.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}}님이 {{attendee}}님과 만납니다. 반복되는 이벤트 중 첫 번째에 대한 세부 사항이 포함된 캘린더 초대 이메일을 모든 사람에게 보냈습니다.",
|
||||
"emailed_you_and_any_other_attendees": "당신과 다른 참여자들이 이 정보가 담긴 이메일을 주고 받았습니다.",
|
||||
"needs_to_be_confirmed_or_rejected": "예약을 확정하거나 취소해주세요.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "되풀이 회의를 여전히 확인 또는 거부해야 합니다.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "아직 팀이 하나도 없습니다.",
|
||||
"no_teams_description": "팀을 통해 다른 사람들이 동료 간 공유된 이벤트를 예약할 수 있습니다.",
|
||||
"submit": "제출하기",
|
||||
"confirm_remove_attribute": "네, 속성을 제거합니다",
|
||||
"remove_attribute": "속성 제거",
|
||||
"remove_attribute_confirmation_message": "속성 '{{name}}'을(를) 제거하시겠습니까? 현재 할당된 모든 사용자가 할당 해제됩니다.",
|
||||
"delete": "지우기",
|
||||
"update": "업데이트",
|
||||
"save": "저장하기",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "전화 번호는 제공됩니다",
|
||||
"before_event_trigger": "이벤트 시작 전",
|
||||
"event_cancelled_trigger": "이벤트 취소 시",
|
||||
"after_hosts_cal_video_no_show": "호스트가 Cal 비디오에 참여하지 않은 후",
|
||||
"after_guests_cal_video_no_show": "게스트가 Cal 비디오에 참여하지 않은 후",
|
||||
"after_hosts_cal_video_no_show": "호스트가 Cal 비디오에 참여하지 않았습니다",
|
||||
"after_guests_cal_video_no_show": "게스트가 Cal 비디오에 참여하지 않았습니다",
|
||||
"new_event_trigger": "새 이벤트 예약 시",
|
||||
"email_host_action": "호스트에게 이메일 발송",
|
||||
"email_attendee_action": "참석자들에게 이메일 전송",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "사용 가능한 시간을 몇 개 선택하여 이메일에 포함시키세요",
|
||||
"select_time": "시간 선택",
|
||||
"select_date": "날짜 선택",
|
||||
"connecting_you_to_someone": "다른 사람과 연결 중입니다.",
|
||||
"connecting_you_to_someone": "{{orgName}}의 담당자와 연결 중입니다.",
|
||||
"please_do_not_close_this_tab": "이 페이지를 닫거나 새로 고침하지 마세요",
|
||||
"see_all_available_times": "모든 사용 가능한 시간 보기",
|
||||
"org_team_names_example_1": "예: 마케팅 팀",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "참석자 시간대의 이벤트 종료 시간",
|
||||
"salesforce_create_event_on_contact": "연락처가 존재하는 경우 이벤트 생성. 그렇지 않으면 리드로 대체",
|
||||
"salesforce_owner_name_to_change": "변경할 소유자 이름",
|
||||
"dont_have_access_this_page": "이 페이지에 접근할 수 없습니다",
|
||||
"you_need_admin_or_owner_privileges_to_access": "이 페이지를 보거나 상호작용하려면 관리자 또는 소유자 권한이 필요합니다",
|
||||
"field_type": "필드 유형",
|
||||
"when_to_write": "작성 시기",
|
||||
"salesforce_on_booking_write_to_record": "예약 시, 참석자 {{record}} 레코드의 사용자 정의 필드에 작성",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "예약 시작 날짜",
|
||||
"booking_created_date": "예약 생성 날짜",
|
||||
"booking_reassigned_to_host": "예약이 {{host}}에게 재할당됨",
|
||||
"access_denied": "접근 거부됨",
|
||||
"salesforce_route_to_owner": "연락처 소유자가 가능하면 Round Robin 호스트가 됩니다.",
|
||||
"salesforce_do_not_route_to_owner": "연락처 소유자가 강제되지 않습니다 (속성과 Round Robin 기준이 일치하면 여전히 호스트가 될 수 있습니다).",
|
||||
"salesforce_route_to_custom_lookup_field": "계정의 조회 필드와 일치하는 사용자에게 라우팅합니다.",
|
||||
"salesforce_option": "Salesforce 옵션",
|
||||
"lookup_field_name": "조회 필드 이름",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 여기에 새 문자열을 추가하세요 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Actie vereist voor verplaatsing: boek een nieuwe tijd voor {{eventType}} met {{name}}",
|
||||
"hi_user_name": "Hallo {{name}}",
|
||||
"ics_event_title": "{{eventType}} met {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oeps, we konden je deze keer niet verbinden. Plan in plaats daarvan een toekomstige oproep.",
|
||||
"please_book_a_time_sometime_later": "Het lijkt erop dat al onze experts momenteel bezet zijn. Plan een gesprek in op een moment dat jou het beste uitkomt en we staan klaar om je te helpen.",
|
||||
"schedule_instead": "Plan in plaats daarvan",
|
||||
"new_event_subject": "Nieuwe afspraak: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Word lid via {{entryPoint}}",
|
||||
"notes": "Opmerkingen",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Overige",
|
||||
"email_sign_in_subject": "Uw aanmeldingslink voor {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Je hebt een afspraak met {{user}}. We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} heeft een afspraak met {{attendee}}. We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd.",
|
||||
"emailed_you_and_attendees": "We hebben u en de andere deelnemende een kalender uitnodiging met alle details gestuurd.",
|
||||
"emailed_host_and_attendee": "We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd.",
|
||||
"emailed_you_and_attendees_recurring": "We hebben u en de andere deelnemers een agenda-uitnodiging voor de eerste van deze terugkerende gebeurtenissen gestuurd.",
|
||||
"emailed_host_and_attendee_recurring": "We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd voor de eerste van deze terugkerende evenementen.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Je hebt een afspraak met {{user}}. We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd voor de eerste van deze terugkerende evenementen.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} heeft een afspraak met {{attendee}}. We hebben een e-mail met een kalenderuitnodiging en de details naar iedereen gestuurd voor de eerste van deze terugkerende evenementen.",
|
||||
"emailed_you_and_any_other_attendees": "U en alle andere deelnemers zijn gemaild met deze informatie.",
|
||||
"needs_to_be_confirmed_or_rejected": "Uw boeking moet nog steeds worden bevestigd of geweigerd.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Uw terugkerende afspraak moet nog steeds bevestigd of geweigerd worden.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "U heeft nog geen teams.",
|
||||
"no_teams_description": "Teams geven anderen de mogelijkheid om gebeurtenissen te boeken die zijn gedeeld tussen uw collega's.",
|
||||
"submit": "Opslaan",
|
||||
"confirm_remove_attribute": "Ja, attribuut verwijderen",
|
||||
"remove_attribute": "Attribuut verwijderen",
|
||||
"remove_attribute_confirmation_message": "Weet u zeker dat u het attribuut '{{name}}' wilt verwijderen? Alle gebruikers die momenteel zijn toegewezen, zullen worden losgekoppeld.",
|
||||
"delete": "Verwijderen",
|
||||
"update": "Bijwerken",
|
||||
"save": "Opslaan",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefoonnummer wordt verstrekt",
|
||||
"before_event_trigger": "voordat de gebeurtenis begint",
|
||||
"event_cancelled_trigger": "wanneer de gebeurtenis is geannuleerd",
|
||||
"after_hosts_cal_video_no_show": "Nadat hosts niet deelnemen aan cal video",
|
||||
"after_guests_cal_video_no_show": "Nadat gasten niet deelnemen aan cal video",
|
||||
"after_hosts_cal_video_no_show": "Nadat hosts niet bij de cal video zijn gekomen",
|
||||
"after_guests_cal_video_no_show": "Nadat gasten niet bij de cal video zijn gekomen",
|
||||
"new_event_trigger": "wanneer een nieuwe gebeurtenis is geboekt",
|
||||
"email_host_action": "e-mail naar organisator versturen",
|
||||
"email_attendee_action": "e-mail naar deelnemers versturen",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Selecteer enkele beschikbare tijden en voeg ze toe aan uw e-mail",
|
||||
"select_time": "Tijd selecteren",
|
||||
"select_date": "Datum selecteren",
|
||||
"connecting_you_to_someone": "We verbinden je met iemand.",
|
||||
"connecting_you_to_someone": "We verbinden je met iemand van {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Sluit of vernieuw deze pagina niet",
|
||||
"see_all_available_times": "Bekijk alle beschikbare tijden",
|
||||
"org_team_names_example_1": "bijvoorbeeld Marketingteam",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Eindtijd evenement in tijdzone deelnemer",
|
||||
"salesforce_create_event_on_contact": "Maak een evenement aan op het contact, indien aanwezig. Anders terugvallen op lead",
|
||||
"salesforce_owner_name_to_change": "Eigenaarsnaam om te wijzigen",
|
||||
"dont_have_access_this_page": "Je hebt geen toegang tot deze pagina",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Om deze pagina te bekijken of ermee te communiceren, moet je over admin- of eigenaarsrechten beschikken",
|
||||
"field_type": "Veldtype",
|
||||
"when_to_write": "Wanneer schrijven",
|
||||
"salesforce_on_booking_write_to_record": "Bij boeking, schrijf naar een aangepast veld op het {{record}}-record van de deelnemer",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Startdatum boeking",
|
||||
"booking_created_date": "Aanmaakdatum boeking",
|
||||
"booking_reassigned_to_host": "Boeking opnieuw toegewezen aan {{host}}",
|
||||
"access_denied": "Toegang geweigerd",
|
||||
"salesforce_route_to_owner": "Contacteigenaar zal de Round Robin host zijn indien beschikbaar",
|
||||
"salesforce_do_not_route_to_owner": "Contacteigenaar wordt niet geforceerd (kan nog steeds host zijn als het overeenkomt met de attributen en Round Robin criteria)",
|
||||
"salesforce_route_to_custom_lookup_field": "Routeer naar een gebruiker die overeenkomt met een zoekveld op een account",
|
||||
"salesforce_option": "Salesforce-optie",
|
||||
"lookup_field_name": "Zoekveldnaam",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Voeg uw nieuwe strings hierboven toe ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Handling Påkrevd: Vennligst book en ny tid for {{eventType}} med {{name}}",
|
||||
"hi_user_name": "Hei {{name}}",
|
||||
"ics_event_title": "{{eventType}} med {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oops, vi kunne ikke koble deg til denne gangen. Vennligst planlegg en samtale senere.",
|
||||
"please_book_a_time_sometime_later": "Det ser ut til at alle våre eksperter er opptatt akkurat nå. Vennligst planlegg en samtale på et tidspunkt som passer best for deg, så vil vi være klare til å hjelpe deg.",
|
||||
"schedule_instead": "Planlegg i stedet",
|
||||
"new_event_subject": "Ny hendelse: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Bli med via {{entryPoint}}",
|
||||
"notes": "Notater",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Annet",
|
||||
"email_sign_in_subject": "Påloggings-lenken din for {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Du skal møte med {{user}}. Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} møter {{attendee}}. Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle.",
|
||||
"emailed_you_and_attendees": "Vi sendte deg og de andre deltakerne en kalenderinvitasjon med alle detaljene.",
|
||||
"emailed_host_and_attendee": "Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle.",
|
||||
"emailed_you_and_attendees_recurring": "Vi sendte deg og de andre deltakerne en kalenderinvitasjon på e-post for den første av disse gjentakende hendelsene.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Du skal møte med {{user}}. Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle for den første av disse gjentakende hendelsene.",
|
||||
"emailed_host_and_attendee_recurring": "Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle for den første av disse gjentakende hendelsene.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Du møter {{user}}. Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle for den første av disse gjentakende hendelsene.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} møter {{attendee}}. Vi har sendt en e-post med en kalenderinvitasjon med detaljene til alle for den første av disse gjentakende hendelsene.",
|
||||
"emailed_you_and_any_other_attendees": "Du og eventuelle andre deltakere har fått e-post med denne informasjonen.",
|
||||
"needs_to_be_confirmed_or_rejected": "Bookingen din må fortsatt bekreftes eller avvises.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Ditt gjentakende møte må fortsatt bekreftes eller avvises.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Du har ingen team ennå.",
|
||||
"no_teams_description": "Team lar andre booke hendelser som deles mellom kollegene dine.",
|
||||
"submit": "Send inn",
|
||||
"confirm_remove_attribute": "Ja, fjern attributt",
|
||||
"remove_attribute": "Fjern attributt",
|
||||
"remove_attribute_confirmation_message": "Er du sikker på at du vil fjerne attributtet '{{name}}'? Alle brukere som for øyeblikket er tildelt det, vil bli fjernet.",
|
||||
"delete": "Slett",
|
||||
"update": "Oppdater",
|
||||
"save": "Lagre",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefonnummer vil bli oppgitt",
|
||||
"before_event_trigger": "før hendelsen starter",
|
||||
"event_cancelled_trigger": "når arrangementet er avlyst",
|
||||
"after_hosts_cal_video_no_show": "Etter at verter ikke blir med på cal video",
|
||||
"after_guests_cal_video_no_show": "Etter at gjester ikke blir med på cal video",
|
||||
"after_hosts_cal_video_no_show": "Etter at vertene ikke møtte opp til cal-videoen",
|
||||
"after_guests_cal_video_no_show": "Etter at gjestene ikke møtte opp til cal-videoen",
|
||||
"new_event_trigger": "når en ny hendelse er booket",
|
||||
"email_host_action": "send e-post til vert",
|
||||
"email_attendee_action": "send e-post til deltakere",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Velg noen tilgjengelige tider og legg dem inn i e-posten din",
|
||||
"select_time": "Velg tid",
|
||||
"select_date": "Velg dato",
|
||||
"connecting_you_to_someone": "Vi kobler deg til noen.",
|
||||
"connecting_you_to_someone": "Vi kobler deg til noen fra {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Vennligst ikke lukk eller oppdater denne siden",
|
||||
"see_all_available_times": "Se alle tilgjengelige tider",
|
||||
"org_team_names_example_1": "f.eks. Markedsføringsteam",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Hendelsens sluttid i deltakers tidssone",
|
||||
"salesforce_create_event_on_contact": "Opprett hendelse på kontakt, hvis den eksisterer. Ellers faller tilbake til lead",
|
||||
"salesforce_owner_name_to_change": "Eiernavn som skal endres",
|
||||
"dont_have_access_this_page": "Du har ikke tilgang til denne siden",
|
||||
"you_need_admin_or_owner_privileges_to_access": "For å se eller bruke denne siden, må du ha administrator- eller eierrettigheter",
|
||||
"field_type": "Felttype",
|
||||
"when_to_write": "Når skal det skrives",
|
||||
"salesforce_on_booking_write_to_record": "Ved booking, skriv til et tilpasset felt på deltaker-{{record}}-posten",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Bookingstart-dato",
|
||||
"booking_created_date": "Dato for opprettet booking",
|
||||
"booking_reassigned_to_host": "Booking omfordelt til {{host}}",
|
||||
"access_denied": "Tilgang nektet",
|
||||
"salesforce_route_to_owner": "Kontaktens eier vil være Round Robin-vert hvis tilgjengelig",
|
||||
"salesforce_do_not_route_to_owner": "Kontaktens eier vil ikke bli tvunget (kan fortsatt være vert hvis det samsvarer med attributtene og Round Robin-kriteriene)",
|
||||
"salesforce_route_to_custom_lookup_field": "Rute til en bruker som samsvarer med et oppslagsfelt på en konto",
|
||||
"salesforce_option": "Salesforce-alternativ",
|
||||
"lookup_field_name": "Oppslagsfeltnavn",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Legg til dine nye strenger over her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Działanie wymagało zmiany harmonogramu: Zarezerwuj nową godzinę na wydarzenie {{eventType}} z {{name}}",
|
||||
"hi_user_name": "Cześć {{name}}",
|
||||
"ics_event_title": "{{eventType}} z {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, nie udało się połączyć tym razem. Proszę zaplanować rozmowę na późniejszy termin.",
|
||||
"please_book_a_time_sometime_later": "Wygląda na to, że wszyscy nasi eksperci są teraz zajęci. Proszę umówić się na rozmowę w dogodnym dla siebie terminie, a my będziemy gotowi, aby Ci pomóc.",
|
||||
"schedule_instead": "Umów się zamiast tego",
|
||||
"new_event_subject": "Nowe wydarzenie: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Dołącz przez {{entryPoint}}",
|
||||
"notes": "Uwagi",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Inne",
|
||||
"email_sign_in_subject": "Twój link logowania do aplikacji {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Spotykasz się z {{user}}. Wysłaliśmy e-mail z zaproszeniem do kalendarza i szczegółami do wszystkich.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} spotka się z {{attendee}}. Wysłaliśmy do wszystkich email z zaproszeniem kalendarzowym zawierającym szczegóły.",
|
||||
"emailed_you_and_attendees": "Wysłaliśmy Ci i innym uczestnikom zaproszenie do kalendarza ze wszystkimi szczegółami.",
|
||||
"emailed_host_and_attendee": "Wysłaliśmy do wszystkich email z zaproszeniem kalendarzowym zawierającym szczegóły.",
|
||||
"emailed_you_and_attendees_recurring": "Wysłaliśmy Ci oraz innym uczestnikom zaproszenie do kalendarza dotyczące pierwszego z tych cyklicznych wydarzeń.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Spotykasz się z {{user}}. Wysłaliśmy e-mail z zaproszeniem do kalendarza i szczegółami do wszystkich na pierwsze z tych cyklicznych wydarzeń.",
|
||||
"emailed_host_and_attendee_recurring": "Wysłaliśmy do wszystkich email z zaproszeniem kalendarzowym zawierającym szczegóły pierwszego z serii cyklicznych spotkań.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Spotkasz się z {{user}}. Wysłaliśmy do wszystkich email z zaproszeniem kalendarzowym zawierającym szczegóły pierwszego z serii cyklicznych spotkań.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} spotka się z {{attendee}}. Wysłaliśmy do wszystkich email z zaproszeniem kalendarzowym zawierającym szczegóły pierwszego z serii cyklicznych spotkań.",
|
||||
"emailed_you_and_any_other_attendees": "Ty i inni uczestnicy dostali e-mail z tymi informacjami.",
|
||||
"needs_to_be_confirmed_or_rejected": "Twoja rezerwacja musi zostać potwierdzona lub odrzucona.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Twoje spotkanie cykliczne musi jeszcze zostać potwierdzone lub odrzucone.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Nie masz jeszcze żadnych drużyn.",
|
||||
"no_teams_description": "Drużyny pozwalają innym na rezerwowanie wydarzeń dzielonych pomiędzy Twoich współpracowników.",
|
||||
"submit": "Prześlij",
|
||||
"confirm_remove_attribute": "Tak, usuń atrybut",
|
||||
"remove_attribute": "Usuń atrybut",
|
||||
"remove_attribute_confirmation_message": "Czy na pewno chcesz usunąć atrybut '{{name}}'? Wszyscy użytkownicy obecnie do niego przypisani zostaną odłączeni.",
|
||||
"delete": "Usuń",
|
||||
"update": "Aktualizuj",
|
||||
"save": "Zapisz",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Numer telefonu zostanie podany.",
|
||||
"before_event_trigger": "przed rozpoczęciem wydarzenia",
|
||||
"event_cancelled_trigger": "gdy wydarzenie zostanie anulowane",
|
||||
"after_hosts_cal_video_no_show": "Po tym, jak gospodarze nie dołączą do wideo na Cal",
|
||||
"after_guests_cal_video_no_show": "Po tym, jak goście nie dołączą do wideo na Cal",
|
||||
"after_hosts_cal_video_no_show": "Po tym, jak gospodarze nie dołączyli do rozmowy wideo",
|
||||
"after_guests_cal_video_no_show": "Po tym, jak goście nie dołączyli do rozmowy wideo",
|
||||
"new_event_trigger": "gdy nowe wydarzenie zostanie zarezerwowane",
|
||||
"email_host_action": "wyślij wiadomość e-mail do hosta",
|
||||
"email_attendee_action": "wyślij wiadomość e-mail do uczestników",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Wybierz kilka dostępnych terminów i osadź je w wiadomości e-mail",
|
||||
"select_time": "Wybierz godzinę",
|
||||
"select_date": "Wybierz datę",
|
||||
"connecting_you_to_someone": "Łączymy Cię z kimś.",
|
||||
"connecting_you_to_someone": "Łączymy Cię z kimś z {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Proszę nie zamykać ani nie odświeżać tej strony",
|
||||
"see_all_available_times": "Zobacz wszystkie dostępne godziny",
|
||||
"org_team_names_example_1": "np. zespół marketingowy",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Czas zakończenia wydarzenia w strefie czasowej uczestnika",
|
||||
"salesforce_create_event_on_contact": "Utwórz wydarzenie na kontakcie, jeśli istnieje. W przeciwnym razie użyj leada",
|
||||
"salesforce_owner_name_to_change": "Nazwa właściciela do zmiany",
|
||||
"dont_have_access_this_page": "Nie masz dostępu do tej strony",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Aby wyświetlić lub korzystać z tej strony, musisz mieć uprawnienia administratora lub właściciela",
|
||||
"field_type": "Typ pola",
|
||||
"when_to_write": "Kiedy zapisać",
|
||||
"salesforce_on_booking_write_to_record": "Przy rezerwacji, zapisz do niestandardowego pola w rekordzie {{record}} uczestnika",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Data rozpoczęcia rezerwacji",
|
||||
"booking_created_date": "Data utworzenia rezerwacji",
|
||||
"booking_reassigned_to_host": "Rezerwacja przypisana ponownie do {{host}}",
|
||||
"access_denied": "Odmowa dostępu",
|
||||
"salesforce_route_to_owner": "Właściciel kontaktu będzie hostem Round Robin, jeśli jest dostępny",
|
||||
"salesforce_do_not_route_to_owner": "Właściciel kontaktu nie będzie wymuszony (może nadal być hostem, jeśli spełnia atrybuty i kryteria Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Przekieruj do użytkownika, który odpowiada polu wyszukiwania w koncie",
|
||||
"salesforce_option": "Opcja Salesforce",
|
||||
"lookup_field_name": "Nazwa pola wyszukiwania",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Dodaj nowe ciągi powyżej ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Ação de reagendamento necessária: reserve outro horário para {{eventType}} com {{name}}",
|
||||
"hi_user_name": "Olá {{name}}",
|
||||
"ics_event_title": "{{eventType}} com {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ops, não foi possível conectá-lo desta vez. Por favor, agende uma chamada mais tarde",
|
||||
"please_book_a_time_sometime_later": "Parece que todos os nossos especialistas estão ocupados no momento. Por favor, agende uma chamada em um horário que seja mais conveniente para você e estaremos prontos para ajudar.",
|
||||
"schedule_instead": "Agendar agora",
|
||||
"new_event_subject": "Novo evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Junte-se através de {{entryPoint}}",
|
||||
"notes": "Notas",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Outras",
|
||||
"email_sign_in_subject": "Seu link de login para {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Você está reunindo-se com {{user}}. Nós enviamos um e-mail com um convite de calendário com todos os detalhes para todos.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} terá uma reunião com {{attendee}}. Enviamos um e-mail com um convite para o calendário contendo todos os detalhes para todos os participantes.",
|
||||
"emailed_you_and_attendees": "Enviamos um e-mail para você e para os outros participantes com um convite de calendário com todos os detalhes.",
|
||||
"emailed_host_and_attendee": "Enviamos um e-mail com um convite para o calendário contendo todos os detalhes para todos os participantes.",
|
||||
"emailed_you_and_attendees_recurring": "Enviamos um e-mail para você e para os outros participantes com um convite de calendário para o primeiro desses eventos recorrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Você está reunindo-se com {{user}}. Nós enviamos um e-mail com um convite de calendário com todos os detalhes para todos com o primeiro destes eventos recorrentes.",
|
||||
"emailed_host_and_attendee_recurring": "Enviamos um e-mail com um convite para o calendário contendo todos os detalhes para todos os participantes para o primeiro destes eventos recorrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Você terá uma reunião com {{user}}. Enviamos um e-mail com um convite para o calendário contendo todos os detalhes para todos os participantes para o primeiro destes eventos recorrentes.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} terá uma reunião com {{attendee}}. Enviamos um e-mail com um convite para o calendário contendo todos os detalhes para todos os participantes para o primeiro destes eventos recorrentes.",
|
||||
"emailed_you_and_any_other_attendees": "Esta informação foi enviada para você e para todos os outros participantes.",
|
||||
"needs_to_be_confirmed_or_rejected": "A sua reserva ainda precisa de ser confirmada ou recusada.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "A sua reunião recorrente ainda precisa ser confirmada ou recusada.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Você ainda não tem nenhuma equipe.",
|
||||
"no_teams_description": "Equipes permitem que outras pessoas reservem eventos compartilhados entre seus colegas de trabalho.",
|
||||
"submit": "Enviar",
|
||||
"confirm_remove_attribute": "Sim, remover atributo",
|
||||
"remove_attribute": "Remover atributo",
|
||||
"remove_attribute_confirmation_message": "Você tem certeza de que deseja remover o atributo '{{name}}'? Todos os usuários atualmente atribuídos a ele serão desassociados.",
|
||||
"delete": "Apagar",
|
||||
"update": "Atualizar",
|
||||
"save": "Salvar",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "O número de telefone será fornecido",
|
||||
"before_event_trigger": "antes do início do evento",
|
||||
"event_cancelled_trigger": "quando o evento for cancelado",
|
||||
"after_hosts_cal_video_no_show": "Após os anfitriões não entrarem no vídeo do Cal",
|
||||
"after_guests_cal_video_no_show": "Após os convidados não entrarem no vídeo do Cal",
|
||||
"after_hosts_cal_video_no_show": "Após os anfitriões não entrarem na videochamada do Cal",
|
||||
"after_guests_cal_video_no_show": "Após os convidados não entrarem na videochamada do Cal",
|
||||
"new_event_trigger": "quando um novo evento for reservado",
|
||||
"email_host_action": "enviar e-mail para a(o) anfitriã(o)",
|
||||
"email_attendee_action": "enviar e-mail aos participantes",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Selecione alguns horários disponíveis e incorpore-os no seu e-mail",
|
||||
"select_time": "Selecione o horário",
|
||||
"select_date": "Selecione a data",
|
||||
"connecting_you_to_someone": "Estamos conectando você a alguém.",
|
||||
"connecting_you_to_someone": "Estamos conectando você a alguém da {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Por favor, não feche ou atualize esta página",
|
||||
"see_all_available_times": "Veja todos os horários disponíveis",
|
||||
"org_team_names_example_1": "ex.: Time de Marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Hora de término do evento no fuso horário do participante",
|
||||
"salesforce_create_event_on_contact": "Criar evento no contato, se existir. Caso contrário, usar lead como alternativa",
|
||||
"salesforce_owner_name_to_change": "Nome do proprietário a ser alterado",
|
||||
"dont_have_access_this_page": "Você não tem acesso a esta página",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Para visualizar ou interagir com esta página, você deve ter privilégios de administrador ou proprietário",
|
||||
"field_type": "Tipo de campo",
|
||||
"when_to_write": "Quando escrever",
|
||||
"salesforce_on_booking_write_to_record": "Ao fazer uma reserva, escrever em um campo personalizado no registro {{record}} do participante",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Data de início da reserva",
|
||||
"booking_created_date": "Data de criação da reserva",
|
||||
"booking_reassigned_to_host": "Reserva reatribuída para {{host}}",
|
||||
"access_denied": "Acesso negado",
|
||||
"salesforce_route_to_owner": "O proprietário do contato será o anfitrião do Round Robin se disponível",
|
||||
"salesforce_do_not_route_to_owner": "O proprietário do contato não será forçado (ainda pode ser anfitrião se corresponder aos atributos e critérios do Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Direcionar para um usuário que corresponda a um campo de pesquisa em uma conta",
|
||||
"salesforce_option": "Opção do Salesforce",
|
||||
"lookup_field_name": "Nome do campo de pesquisa",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione suas novas strings aqui em cima ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Acção necessária para reagendamento: Por favor reserve uma nova hora para {{eventType}} com {{name}}",
|
||||
"hi_user_name": "Olá {{name}}",
|
||||
"ics_event_title": "{{eventType}} com {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ninguém estava disponível no momento. Por favor, faça uma reserva para um horário mais tarde",
|
||||
"please_book_a_time_sometime_later": "Parece que todos os nossos especialistas estão ocupados no momento. Por favor, agende uma chamada em um horário que seja melhor para você e estaremos prontos para ajudá-lo.",
|
||||
"schedule_instead": "Agendar em vez disso",
|
||||
"new_event_subject": "Novo evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Junte-se através de {{entryPoint}}",
|
||||
"notes": "Notas",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Outras",
|
||||
"email_sign_in_subject": "A sua ligação de início de sessão para {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Está a reunir com {{user}}. Enviámos um e-mail para si e para os outros participantes com um convite de calendário com todos os detalhes.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} terá uma reunião com {{attendee}}. Enviamos um e-mail com um convite para o calendário contendo todos os detalhes.",
|
||||
"emailed_you_and_attendees": "Enviámos um email para si e para os outros participantes com um convite de calendário com todos os detalhes.",
|
||||
"emailed_host_and_attendee": "Enviamos um e-mail com um convite para o calendário contendo todos os detalhes.",
|
||||
"emailed_you_and_attendees_recurring": "Enviámos um email para si e para os outros participantes com um convite de calendário para o primeiro destes eventos recorrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Está a reunir com {{user}}. Enviámos um e-mail para si e para os outros participantes com um convite de calendário para o primeiro destes eventos recorrentes.",
|
||||
"emailed_host_and_attendee_recurring": "Enviamos um e-mail com um convite para o calendário contendo os detalhes do primeiro destes eventos recorrentes.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Você terá uma reunião com {{user}}. Enviamos um e-mail com um convite para o calendário contendo os detalhes do primeiro destes eventos recorrentes.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} terá uma reunião com {{attendee}}. Enviamos um e-mail com um convite para o calendário contendo os detalhes do primeiro destes eventos recorrentes.",
|
||||
"emailed_you_and_any_other_attendees": "Esta informação foi enviada para si e para todos os outros participantes.",
|
||||
"needs_to_be_confirmed_or_rejected": "A sua reserva ainda precisa de ser confirmada ou rejeitada.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "A sua reunião recorrente ainda precisa de ser confirmada ou rejeitada.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Ainda não tem nenhuma equipa.",
|
||||
"no_teams_description": "As equipas permitem-lhe reservar eventos partilhados entre os seus colaboradores.",
|
||||
"submit": "Enviar",
|
||||
"confirm_remove_attribute": "Sim, remover atributo",
|
||||
"remove_attribute": "Remover atributo",
|
||||
"remove_attribute_confirmation_message": "Você tem certeza de que deseja remover o atributo '{{name}}'? Todos os usuários atualmente atribuídos a ele serão desassociados.",
|
||||
"delete": "Apagar",
|
||||
"update": "Atualizar",
|
||||
"save": "Guardar",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Será fornecido um número de telefone",
|
||||
"before_event_trigger": "antes do evento iniciar",
|
||||
"event_cancelled_trigger": "quando o evento for cancelado",
|
||||
"after_hosts_cal_video_no_show": "Após os anfitriões não se juntarem ao vídeo do Cal",
|
||||
"after_guests_cal_video_no_show": "Após os convidados não se juntarem ao vídeo do Cal",
|
||||
"after_hosts_cal_video_no_show": "Após os anfitriões não terem participado do vídeo do Cal",
|
||||
"after_guests_cal_video_no_show": "Após os convidados não terem participado do vídeo do Cal",
|
||||
"new_event_trigger": "quando um novo evento for reservado",
|
||||
"email_host_action": "enviar email ao anfitrião",
|
||||
"email_attendee_action": "enviar e-mail aos participantes",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Selecione alguns horários disponíveis e incorpore-os no seu E-mail",
|
||||
"select_time": "Selecionar horário",
|
||||
"select_date": "Selecionar data",
|
||||
"connecting_you_to_someone": "Estamos a conectá-lo a alguém.",
|
||||
"connecting_you_to_someone": "Estamos conectando você a alguém da {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Por favor, não feche ou atualize esta página",
|
||||
"see_all_available_times": "Ver todos os horários disponíveis",
|
||||
"org_team_names_example_1": "Por exemplo, Equipa de Marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Hora de fim do evento no fuso horário do participante",
|
||||
"salesforce_create_event_on_contact": "Criar evento no contacto, se existir. Caso contrário, recorrer ao lead",
|
||||
"salesforce_owner_name_to_change": "Nome do proprietário a alterar",
|
||||
"dont_have_access_this_page": "Você não tem acesso a esta página",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Para visualizar ou interagir com esta página, você deve ter privilégios de administrador ou proprietário",
|
||||
"field_type": "Tipo de campo",
|
||||
"when_to_write": "Quando escrever",
|
||||
"salesforce_on_booking_write_to_record": "Na reserva, escrever num campo personalizado no registo {{record}} do participante",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Data de início da reserva",
|
||||
"booking_created_date": "Data de criação da reserva",
|
||||
"booking_reassigned_to_host": "Reserva reatribuída a {{host}}",
|
||||
"access_denied": "Acesso negado",
|
||||
"salesforce_route_to_owner": "O proprietário do contato será o anfitrião do Round Robin se disponível",
|
||||
"salesforce_do_not_route_to_owner": "O proprietário do contato não será forçado (ainda pode ser anfitrião se corresponder aos atributos e critérios do Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Direcionar para um usuário que corresponda a um campo de pesquisa em uma conta",
|
||||
"salesforce_option": "Opção do Salesforce",
|
||||
"lookup_field_name": "Nome do campo de pesquisa",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Acțiunea necesită reprogramare: rezervați o nouă dată pentru {{eventType}} cu {{name}}",
|
||||
"hi_user_name": "Salut {{name}}",
|
||||
"ics_event_title": "{{eventType}} cu {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, nu te-am putut conecta de această dată. Te rugăm să programezi un apel pentru o dată viitoare.",
|
||||
"please_book_a_time_sometime_later": "Se pare că toți experții noștri sunt ocupați în acest moment. Vă rugăm să programați un apel la un moment care vi se potrivește cel mai bine și vom fi pregătiți să vă asistăm.",
|
||||
"schedule_instead": "Programați în schimb",
|
||||
"new_event_subject": "Eveniment nou: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Alăturați-vă de {{entryPoint}}",
|
||||
"notes": "Notiţe",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Altele",
|
||||
"email_sign_in_subject": "Linkul tău de conectare pentru {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Te întâlnești cu {{user}}. Am trimis un email cu o invitație în calendar cu detaliile către toți participanții.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} se întâlnește cu {{attendee}}. Am trimis un email cu o invitație în calendar cu detaliile către toată lumea.",
|
||||
"emailed_you_and_attendees": "V-am trimis un e-mail dumneavoastră şi celuilalt participant la o invitaţie în calendar cu toate detaliile.",
|
||||
"emailed_host_and_attendee": "Am trimis un email cu o invitație în calendar cu detaliile către toată lumea.",
|
||||
"emailed_you_and_attendees_recurring": "V-am trimis un e-mail dvs. și celorlalți participanți cu o invitație în calendar pentru primul dintre aceste evenimente recurente.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Te întâlnești cu {{user}}. Am trimis un email cu o invitație în calendar cu detaliile către toți participanții pentru primul dintre aceste evenimente recurente.",
|
||||
"emailed_host_and_attendee_recurring": "Am trimis un email cu o invitație în calendar cu detaliile către toată lumea pentru primul dintre aceste evenimente recurente.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Te întâlnești cu {{user}}. Am trimis un email cu o invitație în calendar cu detaliile către toată lumea pentru primul dintre aceste evenimente recurente.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} se întâlnește cu {{attendee}}. Am trimis un email cu o invitație în calendar cu detaliile către toată lumea pentru primul dintre aceste evenimente recurente.",
|
||||
"emailed_you_and_any_other_attendees": "Dumneavoastră şi oricare alţi participanţi aţi primit prin e-mail aceste informaţii.",
|
||||
"needs_to_be_confirmed_or_rejected": "Rezervarea dvs. încă trebuie confirmată sau respinsă.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Întâlnirea dvs. recurentă încă trebuie confirmată sau respinsă.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Încă nu aveți nicio echipă.",
|
||||
"no_teams_description": "Echipele permit altora să rezerve evenimente distribuite între colegii dvs.",
|
||||
"submit": "Trimiteți",
|
||||
"confirm_remove_attribute": "Da, elimină atributul",
|
||||
"remove_attribute": "Elimină atributul",
|
||||
"remove_attribute_confirmation_message": "Ești sigur că vrei să elimini atributul '{{name}}'? Toți utilizatorii care sunt în prezent asociați cu acesta vor fi dezasociați.",
|
||||
"delete": "Şterge",
|
||||
"update": "Actualizează",
|
||||
"save": "Salvează",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Numărul de telefon va fi furnizat",
|
||||
"before_event_trigger": "înainte de începerea evenimentului",
|
||||
"event_cancelled_trigger": "la anularea evenimentului",
|
||||
"after_hosts_cal_video_no_show": "După ce gazdele nu se alătură la cal video",
|
||||
"after_guests_cal_video_no_show": "După ce invitații nu se alătură la cal video",
|
||||
"after_hosts_cal_video_no_show": "După ce gazdele nu s-au alăturat la cal video",
|
||||
"after_guests_cal_video_no_show": "După ce oaspeții nu s-au alăturat la cal video",
|
||||
"new_event_trigger": "când este rezervat noul eveniment",
|
||||
"email_host_action": "trimiteți e-mail la gazdă",
|
||||
"email_attendee_action": "trimiteți e-mail participanților",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Selectați câteva date disponibile și încorporați-le în e-mailul dvs.",
|
||||
"select_time": "Selectați ora",
|
||||
"select_date": "Selectați data",
|
||||
"connecting_you_to_someone": "Te conectăm cu cineva.",
|
||||
"connecting_you_to_someone": "Vă conectăm cu cineva de la {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Vă rugăm să nu închideți sau să reîmprospătați această pagină",
|
||||
"see_all_available_times": "Vedeți toate orele disponibile",
|
||||
"org_team_names_example_1": "de ex. echipa de marketing",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Ora de sfârșit a evenimentului în fusul orar al participantului",
|
||||
"salesforce_create_event_on_contact": "Creați evenimentul pe contact, dacă există. Altfel, reveniți la lead",
|
||||
"salesforce_owner_name_to_change": "Numele proprietarului de schimbat",
|
||||
"dont_have_access_this_page": "Nu aveți acces la această pagină",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Pentru a vizualiza sau interacționa cu această pagină, trebuie să aveți privilegii de administrator sau proprietar",
|
||||
"field_type": "Tip câmp",
|
||||
"when_to_write": "Când să se scrie",
|
||||
"salesforce_on_booking_write_to_record": "La rezervare, scrie într-un câmp personalizat în înregistrarea {{record}} a participantului",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Data de început a rezervării",
|
||||
"booking_created_date": "Data creării rezervării",
|
||||
"booking_reassigned_to_host": "Rezervare reatribuită către {{host}}",
|
||||
"access_denied": "Acces refuzat",
|
||||
"salesforce_route_to_owner": "Proprietarul contactului va fi gazda Round Robin dacă este disponibil",
|
||||
"salesforce_do_not_route_to_owner": "Proprietarul contactului nu va fi forțat (poate fi totuși gazdă dacă se potrivesc atributele și criteriile Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Redirecționează către un utilizator care se potrivește cu un câmp de căutare pe un cont",
|
||||
"salesforce_option": "Opțiune Salesforce",
|
||||
"lookup_field_name": "Nume câmp de căutare",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adăugați stringurile noi deasupra acestui rând ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Promena vremena zahteva radnju: zakažite novo vreme za {{eventType}} sa {{name}}",
|
||||
"hi_user_name": "Zdravo {{name}}",
|
||||
"ics_event_title": "{{eventType}} sa {{name}}",
|
||||
"please_book_a_time_sometime_later": "Ups, nismo uspeli da vas povežemo ovaj put. Molimo vas da zakažete poziv za kasnije.",
|
||||
"please_book_a_time_sometime_later": "Izgleda da su svi naši stručnjaci trenutno zauzeti. Molimo vas da zakažete poziv u vreme koje vam najviše odgovara i bićemo spremni da vam pomognemo.",
|
||||
"schedule_instead": "Zakažite umesto toga",
|
||||
"new_event_subject": "Novi dogadjaj: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Pridruži se putem {{entryPoint}}",
|
||||
"notes": "Beleške",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Drugo",
|
||||
"email_sign_in_subject": "Vaša veza za prijavu na {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Sastajete se sa {{user}}. Poslali smo email sa pozivom na kalendar sa detaljima svima.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} se sastaje sa {{attendee}}. Poslali smo e-mail sa pozivnicom za kalendar sa detaljima svima.",
|
||||
"emailed_you_and_attendees": "Poslali smo vama i ostalim učesnicima kalendarski poziv sa svim detaljima.",
|
||||
"emailed_host_and_attendee": "Poslali smo e-mail sa pozivnicom za kalendar sa detaljima svima.",
|
||||
"emailed_you_and_attendees_recurring": "Poslali smo vama i ostalim učesnicima kalendarski poziv za prvi od ovih ponavljajućih događaja.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Sastajete se sa {{user}}. Poslali smo email sa pozivom na kalendar sa detaljima svima za prvi od ovih ponavljajućih događaja.",
|
||||
"emailed_host_and_attendee_recurring": "Poslali smo e-mail sa pozivnicom za kalendar sa detaljima svima za prvi od ovih ponavljajućih događaja.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Sastajete se sa {{user}}. Poslali smo e-mail sa pozivnicom za kalendar sa detaljima svima za prvi od ovih ponavljajućih događaja.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} se sastaje sa {{attendee}}. Poslali smo e-mail sa pozivnicom za kalendar sa detaljima svima za prvi od ovih ponavljajućih događaja.",
|
||||
"emailed_you_and_any_other_attendees": "Vi i ostali učesnici ste dobili e-poštu sa ovim informacijama.",
|
||||
"needs_to_be_confirmed_or_rejected": "Vaša rezervicija i dalje mora da se potrvrdi ili odbije.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Vaš ponavljajući sastanak i dalje mora da se potvrdi ili odbije.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Još uvek nemate nijedan tim.",
|
||||
"no_teams_description": "Timovi služe za rezervacije dogadjaja koje delite sa vašim kolegama.",
|
||||
"submit": "Podnesi",
|
||||
"confirm_remove_attribute": "Da, ukloni atribut",
|
||||
"remove_attribute": "Ukloni atribut",
|
||||
"remove_attribute_confirmation_message": "Da li ste sigurni da želite da uklonite atribut '{{name}}'? Svi korisnici koji su trenutno dodeljeni ovom atributu biće razdodeljeni.",
|
||||
"delete": "Obriši",
|
||||
"update": "Ažuriraj",
|
||||
"save": "Snimi",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Broj telefona će biti dostavljen",
|
||||
"before_event_trigger": "pre početka događaja",
|
||||
"event_cancelled_trigger": "kada je događaj otkazan",
|
||||
"after_hosts_cal_video_no_show": "Nakon što se domaćini ne pojave na Cal video sastanku",
|
||||
"after_guests_cal_video_no_show": "Nakon što se gosti ne pojave na Cal video sastanku",
|
||||
"after_hosts_cal_video_no_show": "Nakon što se domaćini nisu pojavili na cal video pozivu",
|
||||
"after_guests_cal_video_no_show": "Nakon što se gosti nisu pojavili na cal video pozivu",
|
||||
"new_event_trigger": "kada je zakazan novi događaj",
|
||||
"email_host_action": "pošalji imejl domaćinu",
|
||||
"email_attendee_action": "pošalji imejl učesnicima",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Izaberite nekoliko dostupnih termina i ugradite ih u svoj imejl",
|
||||
"select_time": "Izaberite vreme",
|
||||
"select_date": "Izaberite datum",
|
||||
"connecting_you_to_someone": "Povezujemo vas sa nekim.",
|
||||
"connecting_you_to_someone": "Povezujemo vas sa nekim iz {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Молимо вас да не затварате или освежавате ову страницу",
|
||||
"see_all_available_times": "Pogledajte sva dostupna vremena",
|
||||
"org_team_names_example_1": "npr. Marketing tim",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Vreme završetka događaja u vremenskoj zoni učesnika",
|
||||
"salesforce_create_event_on_contact": "Kreiraj događaj na kontaktu, ako postoji. U suprotnom, prebaci na lead",
|
||||
"salesforce_owner_name_to_change": "Ime vlasnika koje treba promeniti",
|
||||
"dont_have_access_this_page": "Nemate pristup ovoj stranici",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Da biste pregledali ili koristili ovu stranicu, morate imati administratorske ili vlasničke privilegije",
|
||||
"field_type": "Tip polja",
|
||||
"when_to_write": "Kada pisati",
|
||||
"salesforce_on_booking_write_to_record": "Pri rezervaciji, upiši u prilagođeno polje na {{record}} zapisu učesnika",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Datum početka rezervacije",
|
||||
"booking_created_date": "Datum kreiranja rezervacije",
|
||||
"booking_reassigned_to_host": "Rezervacija dodeljena {{host}}-u",
|
||||
"access_denied": "Pristup odbijen",
|
||||
"salesforce_route_to_owner": "Vlasnik kontakta će biti Round Robin domaćin ako je dostupan",
|
||||
"salesforce_do_not_route_to_owner": "Vlasnik kontakta neće biti primoran (može i dalje biti domaćin ako odgovara atributima i Round Robin kriterijumima)",
|
||||
"salesforce_route_to_custom_lookup_field": "Usmeri ka korisniku koji odgovara polju za pretragu na nalogu",
|
||||
"salesforce_option": "Salesforce opcija",
|
||||
"lookup_field_name": "Naziv polja za pretragu",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Dodajte svoje nove stringove iznad ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Åtgärd som krävs Tidsschema: Boka en ny tid för {{eventType}} hos {{name}}",
|
||||
"hi_user_name": "Hej {{name}}",
|
||||
"ics_event_title": "{{eventType}} med {{name}}",
|
||||
"please_book_a_time_sometime_later": "Oj, vi kunde inte ansluta dig den här gången. Vänligen boka ett framtida samtal istället.",
|
||||
"please_book_a_time_sometime_later": "Det verkar som att alla våra experter är upptagna just nu. Vänligen boka ett samtal vid en tidpunkt som passar dig bäst, så hjälper vi dig då.",
|
||||
"schedule_instead": "Boka istället",
|
||||
"new_event_subject": "Ny bokning: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Anslut med {{entryPoint}}",
|
||||
"notes": "Anteckningar",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Annat",
|
||||
"email_sign_in_subject": "Din inloggningslänk för {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Du möter {{user}}. Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} träffar {{attendee}}. Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla.",
|
||||
"emailed_you_and_attendees": "Vi skickade dig och de andra deltagarna en kalenderinbjudan med alla detaljer.",
|
||||
"emailed_host_and_attendee": "Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla.",
|
||||
"emailed_you_and_attendees_recurring": "Vi skickade dig och de andra deltagarna en kalenderinbjudan via e-post för den första av dessa återkommande händelser.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Du möter {{user}}. Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla för det första av dessa återkommande evenemang.",
|
||||
"emailed_host_and_attendee_recurring": "Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla för det första av dessa återkommande evenemang.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Du träffar {{user}}. Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla för det första av dessa återkommande evenemang.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} träffar {{attendee}}. Vi har skickat ett e-postmeddelande med en kalenderinbjudan med detaljerna till alla för det första av dessa återkommande evenemang.",
|
||||
"emailed_you_and_any_other_attendees": "Du och alla andra deltagare har fått e-post med denna information.",
|
||||
"needs_to_be_confirmed_or_rejected": "Din bokning behöver fortfarande bekräftas eller avböjas.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Ditt återkommande möte behöver fortfarande bekräftas eller avböjas.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Du har inga team ännu.",
|
||||
"no_teams_description": "Team tillåter andra att boka gemensamma evenemang mellan dina medarbetare.",
|
||||
"submit": "Skicka",
|
||||
"confirm_remove_attribute": "Ja, ta bort attribut",
|
||||
"remove_attribute": "Ta bort attribut",
|
||||
"remove_attribute_confirmation_message": "Är du säker på att du vill ta bort attributet '{{name}}'? Alla användare som för närvarande är tilldelade det kommer att avregistreras.",
|
||||
"delete": "Radera",
|
||||
"update": "Uppdatera",
|
||||
"save": "Spara",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefonnummer kommer att anges",
|
||||
"before_event_trigger": "innan händelsen startar",
|
||||
"event_cancelled_trigger": "när händelsen ställs in",
|
||||
"after_hosts_cal_video_no_show": "Efter att värdarna inte ansluter till cal video",
|
||||
"after_guests_cal_video_no_show": "Efter att gästerna inte ansluter till cal video",
|
||||
"after_hosts_cal_video_no_show": "Efter att värdarna inte deltog i cal-video",
|
||||
"after_guests_cal_video_no_show": "Efter att gästerna inte deltog i cal-video",
|
||||
"new_event_trigger": "när ny händelse bokas",
|
||||
"email_host_action": "skicka e-post till värd",
|
||||
"email_attendee_action": "skicka e-post till deltagare",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Välj några tillgängliga tider och bädda in dem i din e-post",
|
||||
"select_time": "Välj tid",
|
||||
"select_date": "Välj datum",
|
||||
"connecting_you_to_someone": "Vi kopplar dig till någon.",
|
||||
"connecting_you_to_someone": "Vi kopplar dig till någon från {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Vänligen stäng eller uppdatera inte den här sidan",
|
||||
"see_all_available_times": "Se alla tillgängliga tider",
|
||||
"org_team_names_example_1": "t.ex. marknadsföringsteam",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Händelsens sluttid i deltagarens tidszon",
|
||||
"salesforce_create_event_on_contact": "Skapa händelse på kontakt om den finns, annars fallback till lead",
|
||||
"salesforce_owner_name_to_change": "Ägarnamn att ändra",
|
||||
"dont_have_access_this_page": "Du har inte åtkomst till den här sidan",
|
||||
"you_need_admin_or_owner_privileges_to_access": "För att visa eller interagera med den här sidan måste du ha administratörs- eller ägarprivilegier",
|
||||
"field_type": "Fälttyp",
|
||||
"when_to_write": "När ska det skrivas",
|
||||
"salesforce_on_booking_write_to_record": "Vid bokning, skriv till ett anpassat fält på deltagarens {{record}}-post",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Bokningens startdatum",
|
||||
"booking_created_date": "Bokningens skapandedatum",
|
||||
"booking_reassigned_to_host": "Bokning omtilldelad till {{host}}",
|
||||
"access_denied": "Åtkomst nekad",
|
||||
"salesforce_route_to_owner": "Kontaktägaren blir Round Robin-värd om tillgänglig",
|
||||
"salesforce_do_not_route_to_owner": "Kontaktägaren kommer inte att tvingas (kan fortfarande vara värd om det matchar attributen och Round Robin-kriterierna)",
|
||||
"salesforce_route_to_custom_lookup_field": "Rikta till en användare som matchar ett uppslagsfält på ett konto",
|
||||
"salesforce_option": "Salesforce-alternativ",
|
||||
"lookup_field_name": "Uppslagsfältsnamn",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Yeniden Planlama İşlemi Gerekiyor: Lütfen {{name}} ile {{eventType}} için yeni bir saat belirleyin",
|
||||
"hi_user_name": "Merhaba {{name}}",
|
||||
"ics_event_title": "{{name}} ile {{eventType}}",
|
||||
"please_book_a_time_sometime_later": "Üzgünüz, bu sefer bağlanamadık. Lütfen ileri bir tarih için arama planlayın.",
|
||||
"please_book_a_time_sometime_later": "Görünüşe göre şu anda tüm uzmanlarımız meşgul. Lütfen sizin için en uygun olan bir zamanda bir görüşme planlayın, biz de size yardımcı olmaya hazır olacağız.",
|
||||
"schedule_instead": "Bunun yerine planla",
|
||||
"new_event_subject": "Yeni etkinlik: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "{{entryPoint}} ile katıl",
|
||||
"notes": "Notlar",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Diğer",
|
||||
"email_sign_in_subject": "{{appName}} için giriş bağlantınız",
|
||||
"round_robin_emailed_you_and_attendees": "{{user}} ile görüşüyorsunuz. Detayları içeren bir takvim davetiyesi e-postası herkese gönderildi.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}}, {{attendee}} ile görüşecek. Herkese detayları içeren takvim davetiyesini e-posta ile gönderdik.",
|
||||
"emailed_you_and_attendees": "Size ve diğer katılımcılara tüm ayrıntıları içeren bir takvim daveti e-postası gönderdik.",
|
||||
"emailed_host_and_attendee": "Herkese detayları içeren takvim davetiyesini e-posta ile gönderdik.",
|
||||
"emailed_you_and_attendees_recurring": "Size ve diğer katılımcılara bu yinelenen etkinliklerin ilki için bir takvim daveti e-postası gönderdik.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}} ile görüşüyorsunuz. Bu tekrarlayan etkinliklerin ilki için detayları içeren bir takvim davetiyesi e-postası herkese gönderildi.",
|
||||
"emailed_host_and_attendee_recurring": "Bu tekrarlanan etkinliklerin ilki için herkese detayları içeren takvim davetiyesini e-posta ile gönderdik.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "{{user}} ile görüşeceksiniz. Bu tekrarlanan etkinliklerin ilki için herkese detayları içeren takvim davetiyesini e-posta ile gönderdik.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}}, {{attendee}} ile görüşecek. Bu tekrarlanan etkinliklerin ilki için herkese detayları içeren takvim davetiyesini e-posta ile gönderdik.",
|
||||
"emailed_you_and_any_other_attendees": "Bu bilgiler size ve diğer katılımcılara e-posta ile gönderildi.",
|
||||
"needs_to_be_confirmed_or_rejected": "Rezervasyonunuzun hâlâ onaylanması veya reddedilmesi gerekiyor.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Yinelenen toplantınızın hâlâ onaylanması veya reddedilmesi gerekiyor.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Henüz hiç ekibiniz yok.",
|
||||
"no_teams_description": "Ekipler, iş arkadaşlarınız arasında paylaşılan etkinlik rezervasyonları için diğer kişilere izin verir.",
|
||||
"submit": "Gönder",
|
||||
"confirm_remove_attribute": "Evet, özelliği kaldır",
|
||||
"remove_attribute": "Özelliği kaldır",
|
||||
"remove_attribute_confirmation_message": "'{{name}}' özelliğini kaldırmak istediğinizden emin misiniz? Bu özelliğe atanmış tüm kullanıcıların ataması kaldırılacak.",
|
||||
"delete": "Sil",
|
||||
"update": "Güncelle",
|
||||
"save": "Kaydet",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Telefon numarası sağlanacaktır",
|
||||
"before_event_trigger": "etkinlik başlamadan önce",
|
||||
"event_cancelled_trigger": "etkinlik iptal edildiğinde",
|
||||
"after_hosts_cal_video_no_show": "Ev sahipleri Cal video toplantısına katılmadığında",
|
||||
"after_guests_cal_video_no_show": "Misafirler Cal video toplantısına katılmadığında",
|
||||
"after_hosts_cal_video_no_show": "Ev sahipleri Cal görüntülü görüşmesine katılmadıktan sonra",
|
||||
"after_guests_cal_video_no_show": "Misafirler Cal görüntülü görüşmesine katılmadıktan sonra",
|
||||
"new_event_trigger": "yeni bir etkinlik için rezervasyon yapıldığında",
|
||||
"email_host_action": "organizatöre e-posta gönder",
|
||||
"email_attendee_action": "katılımcılara e-posta gönder",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Uygun zamanlardan bazılarını seçin ve bunları E-postanıza ekleyin",
|
||||
"select_time": "Saati Seçin",
|
||||
"select_date": "Tarihi Seçin",
|
||||
"connecting_you_to_someone": "Sizi birine bağlıyoruz.",
|
||||
"connecting_you_to_someone": "Sizi {{orgName}}'den birisiyle bağlıyoruz.",
|
||||
"please_do_not_close_this_tab": "Lütfen bu sayfayı kapatmayın veya yenilemeyin",
|
||||
"see_all_available_times": "Tüm müsait saatleri görün",
|
||||
"org_team_names_example_1": "Örneğin. Pazarlama ekibi",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Katılımcı Saat Diliminde Etkinlik Bitiş Zamanı",
|
||||
"salesforce_create_event_on_contact": "Eğer varsa, kişi üzerinde etkinlik oluştur. Yoksa potansiyel müşteriye geri dön",
|
||||
"salesforce_owner_name_to_change": "Değiştirilecek sahip adı",
|
||||
"dont_have_access_this_page": "Bu sayfaya erişiminiz yok",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Bu sayfayı görüntülemek veya etkileşimde bulunmak için yönetici veya sahip ayrıcalıklarına sahip olmalısınız",
|
||||
"field_type": "Alan türü",
|
||||
"when_to_write": "Ne zaman yazılacak",
|
||||
"salesforce_on_booking_write_to_record": "Rezervasyon yapıldığında, katılımcının {{record}} kaydındaki özel alana yaz",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Rezervasyon başlangıç tarihi",
|
||||
"booking_created_date": "Rezervasyon oluşturma tarihi",
|
||||
"booking_reassigned_to_host": "Rezervasyon {{host}} kişisine yeniden atandı",
|
||||
"access_denied": "Erişim Reddedildi",
|
||||
"salesforce_route_to_owner": "Mümkünse kişi sahibi round robin ev sahibi olacak",
|
||||
"salesforce_do_not_route_to_owner": "Kişi sahibi zorlanmayacak (özellikler ve round robin kriterlerine uyuyorsa yine de ev sahibi olabilir)",
|
||||
"salesforce_route_to_custom_lookup_field": "Bir hesaptaki arama alanıyla eşleşen bir kullanıcıya yönlendir",
|
||||
"salesforce_option": "Salesforce seçeneği",
|
||||
"lookup_field_name": "Arama alanı adı",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Потрібно перенести бронювання: забронюйте новий час для заходу «{{eventType}}» із користувачем {{name}}",
|
||||
"hi_user_name": "Привіт, {{name}}!",
|
||||
"ics_event_title": "{{eventType}} «{{name}}»",
|
||||
"please_book_a_time_sometime_later": "Ой, ми не можемо підключитися до вас цього разу. Будь ласка, організуйте майбутній дзвінок замість цього",
|
||||
"please_book_a_time_sometime_later": "Схоже, що всі наші експерти зараз зайняті. Будь ласка, заплануйте дзвінок на зручний для вас час, і ми будемо готові вам допомогти.",
|
||||
"schedule_instead": "Запланувати натомість",
|
||||
"new_event_subject": "Новий захід: {{attendeeName}} – {{date}} – {{eventType}}",
|
||||
"join_by_entrypoint": "Приєднатися через {{entryPoint}}",
|
||||
"notes": "Примітки",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Інше",
|
||||
"email_sign_in_subject": "Ваше посилання для входу в {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Ви зустрічаєтеся з {{user}}. Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} зустрічається з {{attendee}}. Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам.",
|
||||
"emailed_you_and_attendees": "Ми надіслали вам та іншим учасникам запрошення до календаря з усіма деталями.",
|
||||
"emailed_host_and_attendee": "Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам.",
|
||||
"emailed_you_and_attendees_recurring": "Ми надіслали вам та іншим учасникам запрошення з календаря на перший із цих періодичних заходів.",
|
||||
"emailed_host_and_attendee_recurring": "Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам для першої з цих повторюваних подій.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Ви зустрічаєтеся з {{user}}. Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам для першої з цих повторюваних подій.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} зустрічається з {{attendee}}. Ми надіслали електронний лист із запрошенням у календар з деталями всім учасникам для першої з цих повторюваних подій.",
|
||||
"emailed_you_and_any_other_attendees": "Цю інформацію надіслано вам і всім іншим учасникам.",
|
||||
"needs_to_be_confirmed_or_rejected": "Ваше бронювання досі потрібно підтвердити або відхилити.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Вашу періодичну нараду досі потрібно підтвердити або відхилити.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "У вас ще немає команд.",
|
||||
"no_teams_description": "Завдяки командам охочі можуть бронювати спільні заходи для ваших колег.",
|
||||
"submit": "Надіслати",
|
||||
"confirm_remove_attribute": "Так, видалити атрибут",
|
||||
"remove_attribute": "Видалити атрибут",
|
||||
"remove_attribute_confirmation_message": "Ви впевнені, що хочете видалити атрибут '{{name}}'? Усі користувачі, які зараз мають цей атрибут, втратять його.",
|
||||
"delete": "Видалити",
|
||||
"update": "Оновити",
|
||||
"save": "Зберегти",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Номер телефону буде надано",
|
||||
"before_event_trigger": "до початку заходу",
|
||||
"event_cancelled_trigger": "у момент скасування заходу",
|
||||
"after_hosts_cal_video_no_show": "Після того, як господарі не приєдналися до відеозустрічі на Cal",
|
||||
"after_guests_cal_video_no_show": "Після того, як гості не приєдналися до відеозустрічі на Cal",
|
||||
"after_hosts_cal_video_no_show": "Після того, як організатори не приєдналися до відеодзвінка",
|
||||
"after_guests_cal_video_no_show": "Після того, як гості не приєдналися до відеодзвінка",
|
||||
"new_event_trigger": "у момент бронювання нового заходу",
|
||||
"email_host_action": "надсилати електронний лист ведучому",
|
||||
"email_attendee_action": "надіслати ел. лист учасникам",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Виберіть кілька доступних часових проміжків і вбудуйте їх в електронний лист",
|
||||
"select_time": "Виберіть час",
|
||||
"select_date": "Виберіть дату",
|
||||
"connecting_you_to_someone": "Ми з'єднуємо вас з кимось.",
|
||||
"connecting_you_to_someone": "Ми з'єднуємо вас із представником {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Будь ласка, не закривайте і не оновлюйте цю сторінку",
|
||||
"see_all_available_times": "Переглянути доступні часові проміжки",
|
||||
"org_team_names_example_1": "напр. команда маркетингу",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Час закінчення події в часовому поясі учасника",
|
||||
"salesforce_create_event_on_contact": "Створити подію для контакту, якщо він існує. В іншому випадку створити для ліда",
|
||||
"salesforce_owner_name_to_change": "Ім'я власника для зміни",
|
||||
"dont_have_access_this_page": "Ви не маєте доступу до цієї сторінки",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Щоб переглядати або взаємодіяти з цією сторінкою, ви повинні мати права адміністратора або власника",
|
||||
"field_type": "Тип поля",
|
||||
"when_to_write": "Коли записувати",
|
||||
"salesforce_on_booking_write_to_record": "При бронюванні, записати в користувацьке поле запису {{record}} учасника",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Дата початку бронювання",
|
||||
"booking_created_date": "Дата створення бронювання",
|
||||
"booking_reassigned_to_host": "Бронювання перепризначено {{host}}",
|
||||
"access_denied": "Доступ заборонено",
|
||||
"salesforce_route_to_owner": "Власник контакту буде ведучим Round Robin, якщо доступний",
|
||||
"salesforce_do_not_route_to_owner": "Власник контакту не буде примусово призначений (може бути ведучим, якщо відповідає атрибутам і критеріям Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Маршрутизація до користувача, який відповідає полю пошуку в обліковому записі",
|
||||
"salesforce_option": "Опція Salesforce",
|
||||
"lookup_field_name": "Назва поля пошуку",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "Thao tác cần làm để xếp lại lịch: Vui lòng đặt thời gian mới cho {{eventType}} với {{name}}",
|
||||
"hi_user_name": "Xin chào {{name}}",
|
||||
"ics_event_title": "{{eventType}} với {{name}}",
|
||||
"please_book_a_time_sometime_later": "Rất tiếc, chúng tôi không thể kết nối bạn lần này. Vui lòng lên lịch cuộc gọi trong tương lai.",
|
||||
"please_book_a_time_sometime_later": "Có vẻ như tất cả các chuyên gia của chúng tôi hiện đang bận. Vui lòng đặt lịch cuộc gọi vào thời gian phù hợp nhất với bạn và chúng tôi sẽ sẵn sàng hỗ trợ bạn.",
|
||||
"schedule_instead": "Thay vào đó, hãy đặt lịch",
|
||||
"new_event_subject": "Sự kiện mới: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "Tham gia bằng {{entryPoint}}",
|
||||
"notes": "Ghi chú",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "Khác",
|
||||
"email_sign_in_subject": "Liên kết đăng nhập cho {{appName}}",
|
||||
"round_robin_emailed_you_and_attendees": "Bạn sẽ gặp {{user}}. Chúng tôi đã gửi email với lời mời lịch và chi tiết cho tất cả mọi người.",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}} sẽ gặp {{attendee}}. Chúng tôi đã gửi email kèm lời mời lịch với đầy đủ thông tin chi tiết đến tất cả mọi người.",
|
||||
"emailed_you_and_attendees": "Chúng tôi đã gửi email cho bạn và những người tham dự khác một lời mời theo lịch hẹn với tất cả các chi tiết đi kèm.",
|
||||
"emailed_host_and_attendee": "Chúng tôi đã gửi email kèm lời mời lịch với đầy đủ thông tin chi tiết đến tất cả mọi người.",
|
||||
"emailed_you_and_attendees_recurring": "Chúng tôi đã gửi email cho bạn và những người tham dự khác một lời mời theo lịch hẹn cho sự kiện định kỳ đầu tiên trong số những sự kiện định kỳ này.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Bạn sẽ gặp {{user}}. Chúng tôi đã gửi email với lời mời lịch và chi tiết cho tất cả mọi người cho sự kiện lặp lại đầu tiên này.",
|
||||
"emailed_host_and_attendee_recurring": "Chúng tôi đã gửi email kèm lời mời lịch với đầy đủ thông tin chi tiết đến tất cả mọi người cho sự kiện đầu tiên trong chuỗi sự kiện định kỳ này.",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "Bạn sẽ gặp {{user}}. Chúng tôi đã gửi email kèm lời mời lịch với đầy đủ thông tin chi tiết đến tất cả mọi người cho sự kiện đầu tiên trong chuỗi sự kiện định kỳ này.",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}} sẽ gặp {{attendee}}. Chúng tôi đã gửi email kèm lời mời lịch với đầy đủ thông tin chi tiết đến tất cả mọi người cho sự kiện đầu tiên trong chuỗi sự kiện định kỳ này.",
|
||||
"emailed_you_and_any_other_attendees": "Bạn và mọi người tham dự khác đã được gửi email với thông tin này.",
|
||||
"needs_to_be_confirmed_or_rejected": "Đặt hẹn của bạn vẫn cần được xác nhận hoặc từ chối.",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "Cuộc họp định kỳ của bạn vẫn cần được xác nhận hoặc từ chối.",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "Bạn chưa có bất kỳ nhóm nào.",
|
||||
"no_teams_description": "Các nhóm cho phép người khác đăng ký các sự kiện được chia sẻ giữa đồng nghiệp của bạn.",
|
||||
"submit": "Gửi đi",
|
||||
"confirm_remove_attribute": "Có, xóa thuộc tính",
|
||||
"remove_attribute": "Xóa thuộc tính",
|
||||
"remove_attribute_confirmation_message": "Bạn có chắc chắn muốn xóa thuộc tính '{{name}}'? Tất cả người dùng hiện đang được gán cho thuộc tính này sẽ bị gỡ gán.",
|
||||
"delete": "Xóa bỏ",
|
||||
"update": "Cập nhật",
|
||||
"save": "Lưu",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "Số điện thoại sẽ được cung ứng",
|
||||
"before_event_trigger": "trước khi sự kiện bắt đầu",
|
||||
"event_cancelled_trigger": "khi sự kiện bị huỷ",
|
||||
"after_hosts_cal_video_no_show": "Sau khi người tổ chức không tham gia video trên Cal",
|
||||
"after_guests_cal_video_no_show": "Sau khi khách mời không tham gia video trên Cal",
|
||||
"after_hosts_cal_video_no_show": "Sau khi người chủ trì không tham gia cuộc gọi video",
|
||||
"after_guests_cal_video_no_show": "Sau khi khách không tham gia cuộc gọi video",
|
||||
"new_event_trigger": "khi sự kiện mới được đặt lịch hẹn",
|
||||
"email_host_action": "gửi email đến chủ sự kiện",
|
||||
"email_attendee_action": "gửi email đến người tham gia",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "Chọn một số thời gian trống và nhúng chúng vào trong Email của bạn",
|
||||
"select_time": "Chọn thời gian",
|
||||
"select_date": "Chọn ngày",
|
||||
"connecting_you_to_someone": "Chúng tôi đang kết nối bạn với ai đó.",
|
||||
"connecting_you_to_someone": "Chúng tôi đang kết nối bạn với một người từ {{orgName}}.",
|
||||
"please_do_not_close_this_tab": "Vui lòng không đóng hoặc làm mới trang này",
|
||||
"see_all_available_times": "Xem tất cả những thời gian trống",
|
||||
"org_team_names_example_1": "ví dụ Nhóm Tiếp thị",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "Thời gian kết thúc sự kiện theo múi giờ của Người tham dự",
|
||||
"salesforce_create_event_on_contact": "Tạo sự kiện trên liên hệ, nếu tồn tại. Nếu không, chuyển sang khách hàng tiềm năng",
|
||||
"salesforce_owner_name_to_change": "Tên chủ sở hữu cần thay đổi",
|
||||
"dont_have_access_this_page": "Bạn không có quyền truy cập trang này",
|
||||
"you_need_admin_or_owner_privileges_to_access": "Để xem hoặc tương tác với trang này, bạn cần có quyền quản trị viên hoặc chủ sở hữu",
|
||||
"field_type": "Loại trường",
|
||||
"when_to_write": "Khi nào ghi",
|
||||
"salesforce_on_booking_write_to_record": "Khi đặt lịch, ghi vào trường tùy chỉnh trên bản ghi {{record}} của người tham dự",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "Ngày bắt đầu đặt lịch",
|
||||
"booking_created_date": "Ngày tạo đặt lịch",
|
||||
"booking_reassigned_to_host": "Đặt lịch được chuyển giao cho {{host}}",
|
||||
"access_denied": "Từ chối truy cập",
|
||||
"salesforce_route_to_owner": "Người sở hữu liên hệ sẽ là người chủ trì Round Robin nếu khả dụng",
|
||||
"salesforce_do_not_route_to_owner": "Người sở hữu liên hệ sẽ không bị bắt buộc (vẫn có thể là người chủ trì nếu phù hợp với các thuộc tính và tiêu chí Round Robin)",
|
||||
"salesforce_route_to_custom_lookup_field": "Chuyển đến người dùng phù hợp với trường tra cứu trên tài khoản",
|
||||
"salesforce_option": "Tùy chọn Salesforce",
|
||||
"lookup_field_name": "Tên trường tra cứu",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "需要重新安排操作: 请为名称为 {{name}} 的 {{eventType}} 预约新的时间",
|
||||
"hi_user_name": "您好 {{name}}",
|
||||
"ics_event_title": "与 {{name}} 的 {{eventType}}",
|
||||
"please_book_a_time_sometime_later": "Oops, 我们无法联系到您。请您另外安排一次计划会议。",
|
||||
"please_book_a_time_sometime_later": "看起来我们所有的专家现在都很忙。请安排一个适合您的时间进行通话,我们将准备好为您提供帮助。",
|
||||
"schedule_instead": "改为安排",
|
||||
"new_event_subject": "新活动: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "由 {{entryPoint}} 加入",
|
||||
"notes": "备注",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "其他",
|
||||
"email_sign_in_subject": "您的 {{appName}} 登录链接",
|
||||
"round_robin_emailed_you_and_attendees": "您将与 {{user}} 会面。我们已向所有人发送了包含详细信息的日历邀请邮件。",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}}将与{{attendee}}会面。我们已向所有人发送了包含详细信息的日历邀请邮件。",
|
||||
"emailed_you_and_attendees": "我们通过电子邮件给您和其他参与者发送了一份包含所有详细信息的日历邀请。",
|
||||
"emailed_host_and_attendee": "我们已向所有人发送了包含详细信息的日历邀请邮件。",
|
||||
"emailed_you_and_attendees_recurring": "我们通过电子邮件给您和其他参与者发送了第一次定期活动的日历邀请。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "您将与 {{user}} 会面。我们已向所有人发送了包含详细信息的日历邀请邮件,适用于这些重复事件的第一次。",
|
||||
"emailed_host_and_attendee_recurring": "我们已向所有人发送了首次循环会议的日历邀请邮件及详细信息。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "您将与{{user}}会面。我们已向所有人发送了首次循环会议的日历邀请邮件及详细信息。",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}}将与{{attendee}}会面。我们已向所有人发送了首次循环会议的日历邀请邮件及详细信息。",
|
||||
"emailed_you_and_any_other_attendees": "已向您和其他参与者发送了关于此信息的电子邮件",
|
||||
"needs_to_be_confirmed_or_rejected": "您的预约仍然需要确认或拒绝。",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "您的定期会议仍然需要确认或拒绝。",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "您还没有任何团队。",
|
||||
"no_teams_description": "团队允许他人预约您和同事共同的活动。",
|
||||
"submit": "提交",
|
||||
"confirm_remove_attribute": "是的,移除属性",
|
||||
"remove_attribute": "移除属性",
|
||||
"remove_attribute_confirmation_message": "您确定要移除属性“{{name}}”吗?所有当前分配到该属性的用户将被取消分配。",
|
||||
"delete": "删除",
|
||||
"update": "更新",
|
||||
"save": "保存",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "将提供电话号码",
|
||||
"before_event_trigger": "活动开始前",
|
||||
"event_cancelled_trigger": "活动取消后",
|
||||
"after_hosts_cal_video_no_show": "主持人未加入 Cal 视频后的处理",
|
||||
"after_guests_cal_video_no_show": "嘉宾未加入 Cal 视频后的处理",
|
||||
"after_hosts_cal_video_no_show": "主持人未加入 Cal 视频后",
|
||||
"after_guests_cal_video_no_show": "嘉宾未加入 Cal 视频后",
|
||||
"new_event_trigger": "预约新活动时",
|
||||
"email_host_action": "向主持人发送电子邮件",
|
||||
"email_attendee_action": "向参与者发送电子邮件",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "选择几个可预约时间并将它们嵌入到您的电子邮件",
|
||||
"select_time": "选择时间",
|
||||
"select_date": "选择日期",
|
||||
"connecting_you_to_someone": "我们正在为您创建连接",
|
||||
"connecting_you_to_someone": "我们正在为您接通{{orgName}}的工作人员。",
|
||||
"please_do_not_close_this_tab": "请不要关闭或刷新此页面",
|
||||
"see_all_available_times": "查看所有可预约时间",
|
||||
"org_team_names_example_1": "例如,营销团队",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "参与者时区的事件结束时间",
|
||||
"salesforce_create_event_on_contact": "如果联系人存在,则在联系人上创建事件。否则回退到潜在客户",
|
||||
"salesforce_owner_name_to_change": "要更改的所有者名称",
|
||||
"dont_have_access_this_page": "您无权访问此页面",
|
||||
"you_need_admin_or_owner_privileges_to_access": "要查看或操作此页面,您必须拥有管理员或所有者权限",
|
||||
"field_type": "字段类型",
|
||||
"when_to_write": "何时写入",
|
||||
"salesforce_on_booking_write_to_record": "预约时,写入参与者 {{record}} 记录的自定义字段",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "预约开始日期",
|
||||
"booking_created_date": "预约创建日期",
|
||||
"booking_reassigned_to_host": "预约重新分配给 {{host}}",
|
||||
"access_denied": "访问被拒绝",
|
||||
"salesforce_route_to_owner": "如果联系人所有者可用,将作为轮询主持人",
|
||||
"salesforce_do_not_route_to_owner": "不会强制指定联系人所有者(如果符合属性和轮询标准,仍可成为主持人)",
|
||||
"salesforce_route_to_custom_lookup_field": "路由至与账户查找字段匹配的用户",
|
||||
"salesforce_option": "Salesforce选项",
|
||||
"lookup_field_name": "查找字段名称",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
"requested_to_reschedule_subject_attendee": "需進行重新預約操作:請為與 {{name}} 的 {{eventType}} 預訂新時間",
|
||||
"hi_user_name": "哈囉 {{name}}",
|
||||
"ics_event_title": "與 {{name}} 的 {{eventType}}",
|
||||
"please_book_a_time_sometime_later": "抱歉,這次無法連接。請改為安排未來的通話。",
|
||||
"please_book_a_time_sometime_later": "目前我們的專家都在忙碌中。請選擇一個最適合您的時間預約通話,我們將準備好為您提供協助。",
|
||||
"schedule_instead": "立即預約",
|
||||
"new_event_subject": "新活動:{{attendeeName}} - {{date}} - {{eventType}}",
|
||||
"join_by_entrypoint": "透過 {{entryPoint}} 加入",
|
||||
"notes": "備註",
|
||||
@@ -350,9 +351,13 @@
|
||||
"other": "其它",
|
||||
"email_sign_in_subject": "您的「{{appName}}」登入連結",
|
||||
"round_robin_emailed_you_and_attendees": "您將與 {{user}} 會面。我們已向所有人發送了包含詳細資訊的日曆邀請。",
|
||||
"round_robin_emailed_host_and_attendee": "{{host}}將與{{attendee}}會面。我們已向所有人發送含有詳細資訊的行事曆邀請郵件。",
|
||||
"emailed_you_and_attendees": "已經寄出行事曆邀請,包含其他與會者都會收到有全部細節的電子郵件。",
|
||||
"emailed_host_and_attendee": "我們已向所有人發送含有詳細資訊的行事曆邀請郵件。",
|
||||
"emailed_you_and_attendees_recurring": "已就這系列定期活動的首次活動,寄出行事曆邀請給您和其他與會者。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "您將與 {{user}} 會面。我們已向所有人發送了包含詳細資訊的日曆邀請,這是這些重複事件中的第一次。",
|
||||
"emailed_host_and_attendee_recurring": "我們已向所有人發送首次週期性會議的行事曆邀請郵件及詳細資訊。",
|
||||
"round_robin_emailed_you_and_attendees_recurring": "您將與{{user}}會面。我們已向所有人發送首次週期性會議的行事曆邀請郵件及詳細資訊。",
|
||||
"round_robin_emailed_host_and_attendee_recurring": "{{host}}將與{{attendee}}會面。我們已向所有人發送首次週期性會議的行事曆邀請郵件及詳細資訊。",
|
||||
"emailed_you_and_any_other_attendees": "您與其他與會者已經收到這份資訊的電子郵件。",
|
||||
"needs_to_be_confirmed_or_rejected": "此預約仍得經過確認,或遭到拒絕。",
|
||||
"needs_to_be_confirmed_or_rejected_recurring": "您的定期會議仍需確認或拒絕。",
|
||||
@@ -705,6 +710,9 @@
|
||||
"no_teams": "還沒有任何團隊。",
|
||||
"no_teams_description": "團隊可以讓其他人預約在同事之間分享的活動。",
|
||||
"submit": "送出",
|
||||
"confirm_remove_attribute": "是的,移除屬性",
|
||||
"remove_attribute": "移除屬性",
|
||||
"remove_attribute_confirmation_message": "您確定要移除屬性 '{{name}}' 嗎?所有目前被指派的使用者將會被取消指派。",
|
||||
"delete": "刪除",
|
||||
"update": "更新",
|
||||
"save": "儲存",
|
||||
@@ -1239,8 +1247,8 @@
|
||||
"number_provided": "將提供電話號碼",
|
||||
"before_event_trigger": "活動開始前",
|
||||
"event_cancelled_trigger": "活動取消時",
|
||||
"after_hosts_cal_video_no_show": "主持人未加入 Cal 視訊後",
|
||||
"after_guests_cal_video_no_show": "賓客未加入 Cal 視訊後",
|
||||
"after_hosts_cal_video_no_show": "主持人未加入視訊會議後",
|
||||
"after_guests_cal_video_no_show": "訪客未加入視訊會議後",
|
||||
"new_event_trigger": "預約新活動時",
|
||||
"email_host_action": "傳送電子郵件給主辦者",
|
||||
"email_attendee_action": "傳送電子郵件給與會者",
|
||||
@@ -2207,7 +2215,7 @@
|
||||
"add_times_to_your_email": "選取幾個開放預約的時段,然後嵌入您的電子郵件",
|
||||
"select_time": "選取時間",
|
||||
"select_date": "選取日期",
|
||||
"connecting_you_to_someone": "我們正在為您連接某人。",
|
||||
"connecting_you_to_someone": "我們正在為您連接 {{orgName}} 的人員。",
|
||||
"please_do_not_close_this_tab": "請勿關閉或重新整理此頁面",
|
||||
"see_all_available_times": "查看所有可預約時段",
|
||||
"org_team_names_example_1": "例如行銷團隊",
|
||||
@@ -2742,6 +2750,8 @@
|
||||
"event_end_time_in_attendee_timezone_info": "參與者時區的活動結束時間",
|
||||
"salesforce_create_event_on_contact": "如果聯絡人存在,則在聯絡人上建立事件。否則回退到潛在客戶",
|
||||
"salesforce_owner_name_to_change": "要更改的擁有者名稱",
|
||||
"dont_have_access_this_page": "您無權存取此頁面",
|
||||
"you_need_admin_or_owner_privileges_to_access": "若要查看或使用此頁面,您必須具有管理員或擁有者權限",
|
||||
"field_type": "欄位類型",
|
||||
"when_to_write": "何時寫入",
|
||||
"salesforce_on_booking_write_to_record": "預約時,寫入參與者 {{record}} 記錄的自定義欄位",
|
||||
@@ -2750,5 +2760,11 @@
|
||||
"booking_start_date": "預約開始日期",
|
||||
"booking_created_date": "預約創建日期",
|
||||
"booking_reassigned_to_host": "預約重新分配給 {{host}}",
|
||||
"access_denied": "拒絕存取",
|
||||
"salesforce_route_to_owner": "如果聯絡人負責人可用,將成為Round Robin主持人",
|
||||
"salesforce_do_not_route_to_owner": "不會強制指定聯絡人負責人(如果符合屬性和Round Robin條件,仍可成為主持人)",
|
||||
"salesforce_route_to_custom_lookup_field": "路由至符合帳戶查詢欄位的使用者",
|
||||
"salesforce_option": "Salesforce選項",
|
||||
"lookup_field_name": "查詢欄位名稱",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 請在此處新增您的字串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
+1078
-315
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ title: "Webhooks"
|
||||
|
||||
|
||||
Webhooks offer a great way to automate the flow with other apps when invitees schedule, cancel or reschedule events, or when the meeting ends.
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Yy9me5E09LA?si=_2Mz-CKL2ajsFivd" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
<iframe style={{ width: "100%", maxWidth: "560px" }} height="315" src="https://www.youtube.com/embed/Yy9me5E09LA?si=_2Mz-CKL2ajsFivd" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
The webhook subscription allows you to listen to specific trigger events, such as when a booking has been scheduled, for example. You can always listen to the webhook by providing a custom subscriber URL with your own development work. However, if you wish to trigger automations without any development work, you can use the integration with Zapier which connects Cal.com to your apps.
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function ConnectCalendar() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.AppleCalendar />
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -23,9 +23,9 @@ For a demonstration of the Apple calendar connect integration, please refer to t
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
height="315"
|
||||
src="https://www.loom.com/embed/0db65d94754443ae91fed28f9bc10509?sid=d7b823cc-cda1-4d18-881a-aa49242b873d"
|
||||
src="https://www.loom.com/embed/0db65d94754443ae91fed28f9bc10509?sid=8389e585-ab9c-457f-944f-82ec7e595f13"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen="true"
|
||||
@@ -44,9 +44,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function ConnectCalendar() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.AppleCalendar isMultiCalendar={true} />
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -56,9 +56,9 @@ For a demonstration of the Apple calendar connect integration for multiple users
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
src="https://www.loom.com/embed/5844146fbcf840f99e35f9620a34186d?sid=a13f4ebf-f565-4488-8352-4e68080ef237"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/5844146fbcf840f99e35f9620a34186d"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen="true"
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function Availability() {
|
||||
console.log("Deleted schedule successfully");
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -35,8 +35,8 @@ For a demonstration of the availability settings atom, please refer to the video
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/6fd65789f5744227b4ea6d0189d4fc67?sid=544a6afd-2836-4704-aa56-e801cbd93cbc"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -64,7 +64,7 @@ export default function Availability() {
|
||||
console.log("Deleted schedule successfully");
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -74,8 +74,8 @@ For a demonstration of the availability settings atom with date overrides, pleas
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/aa9ba47cbc284496ac51c26e172c7b12?sid=6d2b5bb3-d2eb-4a95-adb5-c67d863d4e34"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function Booker( props : BookerProps ) {
|
||||
console.log("booking created successfully");
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -29,8 +29,8 @@ For a demonstration of the booker atom, please refer to the video below.
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/73dbb943cef0409c9bc57d5050453a6e?sid=45575c09-4786-486e-99f9-6cf7f4e8db50"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -57,7 +57,7 @@ export default function Booker( props : BookerProps ) {
|
||||
console.log("booking created successfully");
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -67,8 +67,8 @@ For a demonstration of the booker atom along with calendar overlay, please refer
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/554e9ef9f7874cbe9d179b63cc2c601b?sid=fc185a1c-1fb9-4705-a222-8ccd131bd5b6"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function CalendarSettingsComponent() {
|
||||
return (
|
||||
<>
|
||||
<CalendarSettings />
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -22,8 +22,8 @@ For a demonstration of the calendar settings atom, please refer to the video bel
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/7f6969363b8743abafcec3974f281987?sid=493e7b5d-b3ae-4821-94a3-972260630e6c"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -64,7 +64,7 @@ export default function DestinationCalendars() {
|
||||
return (
|
||||
<>
|
||||
<DestinationCalendarSettings classNames="mx-5" statusLoader={loadingStatus} />
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -91,7 +91,7 @@ export default function SelectedCalendars( props : SelectedCalendarsProps ) {
|
||||
return (
|
||||
<>
|
||||
<SelectedCalendarSettings classNames="mx-5 mb-6" />
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -33,8 +33,8 @@ For a demonstration of the create event type atom, please refer to the video bel
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/b0c5d0599b2c48cdbba288b0b772a676?sid=5a1dbf17-8fc4-41f1-8d77-b36332546989"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -75,8 +75,8 @@ For a demonstration of the create event type atom, please refer to the video bel
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/281c18a1a61c4c44b0bdfd3c88ced8e8?sid=ca68ef1d-eb08-4e23-bd94-9a22a8f7aa7d"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -135,8 +135,8 @@ For a demonstration of the event type settings atom, please refer to the video b
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/2e94c5699dec4fd09d7804d2fd39d71e?sid=04ea09e9-25c3-43cc-be07-33b4b2f32c17"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -209,8 +209,8 @@ Below video shows a demonstration of the limits tab.
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/ac02d393c923413aaa97ab29b43eed48?sid=c130e621-d8e2-4e22-9614-fee97053a194"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -228,8 +228,8 @@ Below video shows a demonstration of the all the options you get in the advanced
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/e0121b51920544eea92251dba99245fa?sid=ac627de7-5673-41b4-aa78-c6c9e439bdb5"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -11,9 +11,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function Connect() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.GoogleCalendar />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -23,8 +23,8 @@ For a demonstration of the Google calendar connect integration, please refer to
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/dcfcaf8c25754b8daec8fe309fbf7c7c?sid=3181cba5-2e16-4f6e-99de-4408a5109c37"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -42,9 +42,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function Connect() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.GoogleCalendar isMultiCalendar={true} />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -54,8 +54,8 @@ For a demonstration of the Google calendar connect integration for multiple user
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/7a34123b3bd94fbc80809392aab5f712?sid=12bacd7e-62b2-40aa-9fd6-30d69ab22e0a"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -11,9 +11,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function ConnectCalendar() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.OutlookCalendar />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -23,8 +23,8 @@ For a demonstration of the Google calendar connect integration, please refer to
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/2da4cdfe8d314f74a55e98121dcdb7bd?sid=cdc73356-13c0-49ba-90a3-91d885251457"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -42,9 +42,9 @@ import { Connect } from "@calcom/atoms";
|
||||
|
||||
export default function ConnectCalendar() {
|
||||
return (
|
||||
<main>
|
||||
<>
|
||||
<Connect.OutlookCalendar isMultiCalendar={true} />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
@@ -54,8 +54,8 @@ For a demonstration of the Outlook calendar connect integration for multiple use
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/b90c21c2bc9c478f9c28c1ee62bb8568?sid=fe1af433-e6e6-4149-9fe2-d3cdbc7d6ca1"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -23,8 +23,8 @@ For a demonstration of the Payment form, please refer to the video below.
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/13cf66446b554d5c9405f9d4fef53f47?sid=d2994785-027e-4de7-937a-3b90fc357182"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
@@ -126,8 +126,8 @@ Below video shows a demonstration of how we combined the event types atom and pa
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/0c1bc59da8c34d83b8dfcbd7557f7eaa?sid=058cf5df-1e3a-4fe3-b721-8c5a9eac4f24"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
|
||||
@@ -35,6 +35,7 @@ export default function Bookings(props: { calUsername: string; calEmail: string
|
||||
return (
|
||||
<p>{booking.title}</p>
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
An example implementation can be found [here](https://github.com/calcom/cal.com/blob/main/packages/platform/examples/base/src/pages/%5BbookingUid%5D.tsx).
|
||||
|
||||
@@ -6,10 +6,10 @@ Install desired apps in your self-hosted instance for better integration.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card href="/self-hosting/apps/install-apps/google" title="Google" icon="google">
|
||||
Install google for supporting Google Calendar and Google Meet integrations
|
||||
Install Google for supporting Google Calendar and Google Meet integrations
|
||||
</Card>
|
||||
<Card href="/self-hosting/apps/install-apps/microsoft" title="Microsoft" icon="microsoft">
|
||||
Install microsoft to support Exchange365 integration
|
||||
Install Microsoft to support Exchange365 integration
|
||||
</Card>
|
||||
<Card href="/self-hosting/apps/install-apps/zoom" title="Zoom" icon="z">
|
||||
Install Zoom to support Zoom video conferencing integration
|
||||
@@ -17,11 +17,11 @@ Install desired apps in your self-hosted instance for better integration.
|
||||
<Card href="/self-hosting/apps/install-apps/daily" title="Daily" icon="video">
|
||||
Install Daily to support Cal Video integration
|
||||
</Card>
|
||||
<Card href="/self-hosting/apps/install-apps/hubspot" title="Hubspot" icon="hubspot">
|
||||
Install Hubspot to support Hubspot CRM integration
|
||||
<Card href="/self-hosting/apps/install-apps/hubspot" title="HubSpot" icon="hubspot">
|
||||
Install HubSpot to support HubSpot CRM integration
|
||||
</Card>
|
||||
<Card href="/self-hosting/apps/install-apps/sendgrid" title="Sendgrid" icon="envelope">
|
||||
Install Sendgrid to support Sendgrid Email integration
|
||||
<Card href="/self-hosting/apps/install-apps/sendgrid" title="SendGrid" icon="envelope">
|
||||
Install SendGrid to support SendGrid Email integration
|
||||
</Card>
|
||||
<Card href="/self-hosting/apps/install-apps/stripe" title="Stripe" icon="stripe">
|
||||
Install Stripe to support Stripe integration for paid bookings
|
||||
|
||||
@@ -141,7 +141,8 @@ checksums:
|
||||
requested_to_reschedule_subject_attendee: 8c41aa43f412fd739407d9a1eaa82c15
|
||||
hi_user_name: fc0d6128cf9a150638e635d2b2aa7397
|
||||
ics_event_title: ad10ef33288a55748e6001607d528ff3
|
||||
please_book_a_time_sometime_later: 89f131f8b3c7b4bc1a288a0ba052541c
|
||||
please_book_a_time_sometime_later: 5353ec92d16f02eba6365819fddfc215
|
||||
schedule_instead: d09667d846cefe86d8a1275a6624b310
|
||||
new_event_subject: eea212a9fd5e66baf8b983b8bc9d7d63
|
||||
join_by_entrypoint: 116d507f1b3a64cd2538e1073935173c
|
||||
notes: 93c7ef9bc767f51fbe360afcf6b1fecb
|
||||
@@ -352,9 +353,13 @@ checksums:
|
||||
other: 79acaa6cd481262bea4e743a422529d2
|
||||
email_sign_in_subject: d67308a3262ab416c083ca041b8690a1
|
||||
round_robin_emailed_you_and_attendees: 74b9d35a245724c3d901ea28a3221484
|
||||
round_robin_emailed_host_and_attendee: 32b8afb73c8d2622e80419dc5c91b483
|
||||
emailed_you_and_attendees: e0f8269315964727ff509f17db78dec8
|
||||
emailed_host_and_attendee: e0f8269315964727ff509f17db78dec8
|
||||
emailed_you_and_attendees_recurring: ba5f9605b0e0f16d97cc1a4462c52924
|
||||
round_robin_emailed_you_and_attendees_recurring: 7166cfe983fb8d1dfcb0e816e599fec2
|
||||
emailed_host_and_attendee_recurring: ba5f9605b0e0f16d97cc1a4462c52924
|
||||
round_robin_emailed_you_and_attendees_recurring: e38959c47e3f9cf24a8cd819c5fa2fbd
|
||||
round_robin_emailed_host_and_attendee_recurring: 340b6e5ec29b7f478e1a08106c10a9b3
|
||||
emailed_you_and_any_other_attendees: 91fdd4bf3fb673086ebcbda8d8983b32
|
||||
needs_to_be_confirmed_or_rejected: 913a2d9efd305e965aac50a6687e47f8
|
||||
needs_to_be_confirmed_or_rejected_recurring: 3f4cdc1672c21265f74da0481ff31972
|
||||
@@ -707,6 +712,9 @@ checksums:
|
||||
no_teams: b629f2ff400fbd38f3b34a25295f0146
|
||||
no_teams_description: 6394f038a3b71bf2036e82443e72591a
|
||||
submit: 7c91ef5f747eea9f77a9c4f23e19fb2e
|
||||
confirm_remove_attribute: 2f3b1cba07ed6ba4f87e157db59800cc
|
||||
remove_attribute: 72944218312442e483aa41eb63abee24
|
||||
remove_attribute_confirmation_message: 356cd8163f04fbc9b9861f2a74131ec9
|
||||
delete: 8bcf303dd10a645b5baacb02b47d72c9
|
||||
update: 079fc039262fd31b10532929685c2d1b
|
||||
save: f7a2929f33bc420195e59ac5a8bcd454
|
||||
@@ -1241,8 +1249,8 @@ checksums:
|
||||
number_provided: 3486dd81e0aace30d7d39116a512dc77
|
||||
before_event_trigger: 8f4c3aa39367d1e1d22d0380ba73591c
|
||||
event_cancelled_trigger: b5d22f397e0f564fcf431032b75ff1af
|
||||
after_hosts_cal_video_no_show: 6b190531cc1bd5f00a6d3a31188d277c
|
||||
after_guests_cal_video_no_show: e5833aeb28ef1004fbeae2c91754d3e7
|
||||
after_hosts_cal_video_no_show: 3ad095ab31649d79abbaf4fff4460bf5
|
||||
after_guests_cal_video_no_show: edf9db3ae09d0d89406efb1656d31820
|
||||
new_event_trigger: fbee38b5765412419941add7ff1e3fb9
|
||||
email_host_action: 9566929caf21c96cedc11447e1de34ff
|
||||
email_attendee_action: 3ca2ca348baef93742f3a1889ffcc96b
|
||||
@@ -2209,7 +2217,7 @@ checksums:
|
||||
add_times_to_your_email: 572a04f56df1ec2623ea7ee8c9c9c5bb
|
||||
select_time: cb9cc2393ca45c6faea13fe4c9d4d6a5
|
||||
select_date: 1e6063bfd25d982048726ff586df55dc
|
||||
connecting_you_to_someone: 4fb9cd52b2caacf09de19b843407d1a9
|
||||
connecting_you_to_someone: 23f139181e74b0afe63cc9493e1f41bd
|
||||
please_do_not_close_this_tab: 0fc355011de61686ff1dd5606336a33a
|
||||
see_all_available_times: 4213ac0595fa798d9c140e13ec5b1133
|
||||
org_team_names_example_1: 6dcddcb08fbac91d1eee90340088b33c
|
||||
@@ -2744,6 +2752,8 @@ checksums:
|
||||
event_end_time_in_attendee_timezone_info: 82ffc6118c662094eb130b74a1e59627
|
||||
salesforce_create_event_on_contact: 82fe69b4ba08b1cb9c6465dc18f968b5
|
||||
salesforce_owner_name_to_change: 000522ab557b02cfe4a5d49787259ef9
|
||||
dont_have_access_this_page: c2341fe363c89498d3d0deb64f3977b1
|
||||
you_need_admin_or_owner_privileges_to_access: 7f032471f243015def700f16681274b2
|
||||
field_type: 7444da76fa3572d47ea5b5d86c50f11f
|
||||
when_to_write: 2dab9955e5743f1bf39ee5066c5c3e91
|
||||
salesforce_on_booking_write_to_record: 43d786b0d3f592a6b1d75ec567f43c70
|
||||
@@ -2752,4 +2762,10 @@ checksums:
|
||||
booking_start_date: ef6f4addaa24a5c7dce41b4d91868ba6
|
||||
booking_created_date: 902300aaa13a56a2295d561d46073eeb
|
||||
booking_reassigned_to_host: 9eb99d1201d75ac0366daf0f09bc360a
|
||||
access_denied: 589456a5c4103e29c44e9df16a4eaf82
|
||||
salesforce_route_to_owner: 39a88a7afb1c1e8fb9215e27ae7a7033
|
||||
salesforce_do_not_route_to_owner: bcae6e5615c17b809c2334a541f75e78
|
||||
salesforce_route_to_custom_lookup_field: 672a24e4de55eb073559e94b9266da7d
|
||||
salesforce_option: f09423b2785ee269db428163fc0a58d0
|
||||
lookup_field_name: 8d81d557128a52661d1ed9e9aae0575c
|
||||
ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS: 18323f2f3fabb169a7cb50ff62433850
|
||||
|
||||
@@ -9,7 +9,6 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultHandler, defaultResponder } from "@calcom/lib/server";
|
||||
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
|
||||
import { GoogleRepository } from "@calcom/lib/server/repository/google";
|
||||
import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import getInstalledAppPath from "../../_utils/getInstalledAppPath";
|
||||
|
||||
@@ -19,11 +19,6 @@ export async function getAllCalendars(
|
||||
|
||||
allCalendars = [...allCalendars, ...(response.data.items ?? [])];
|
||||
pageToken = response.data.nextPageToken;
|
||||
|
||||
logger.error("Google Calendar pagination failed in the middle", {
|
||||
totalSoFar: allCalendars.length,
|
||||
hasMorePages: !!pageToken,
|
||||
});
|
||||
} while (pageToken);
|
||||
|
||||
return allCalendars;
|
||||
|
||||
@@ -87,20 +87,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
id: formId,
|
||||
...entityPrismaWhereClause({ userId: user.id }),
|
||||
},
|
||||
include: {
|
||||
team: {
|
||||
select: {
|
||||
members: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!form) {
|
||||
return res.status(404).json({ message: "Form not found or unauthorized" });
|
||||
}
|
||||
|
||||
if (!canEditEntity(form, user.id)) {
|
||||
if (!(await canEditEntity(form, user.id))) {
|
||||
return res.status(404).json({ message: "Form not found or unauthorized" });
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import routingFormBookingFormHandler from "../salesforce/lib/routingFormBookingFormHandler";
|
||||
import type { AttributeRoutingConfig } from "./types/types";
|
||||
|
||||
type AppBookingFormHandler = (
|
||||
attendeeEmail: string,
|
||||
attributeRoutingConfig: AttributeRoutingConfig,
|
||||
eventTypeId: number
|
||||
) => Promise<{ email: string | null }>;
|
||||
|
||||
const appBookingFormHandler: Record<string, AppBookingFormHandler> = {
|
||||
salesforce: routingFormBookingFormHandler,
|
||||
};
|
||||
|
||||
export default appBookingFormHandler;
|
||||
@@ -0,0 +1,5 @@
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
export const routingFormAppComponents = {
|
||||
salesforce: dynamic(() => import("../salesforce/components/RoutingFormOptions")),
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { routingFormOptions as salesforce_routing_form_schema } from "../salesforce/zod";
|
||||
|
||||
export const routingFormAppDataSchemas = {
|
||||
salesforce: salesforce_routing_form_schema,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { Route, AttributeRoutingConfig } from "../types/types";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export default function DynamicAppComponent<T extends Record<string, React.ComponentType<any>>>(props: {
|
||||
componentMap: T;
|
||||
slug: string;
|
||||
appData: any;
|
||||
route: Route;
|
||||
setAttributeRoutingConfig: (id: string, attributeRoutingConfig: Partial<AttributeRoutingConfig>) => void;
|
||||
wrapperClassName?: string;
|
||||
}) {
|
||||
const { componentMap, slug, wrapperClassName, appData, route, setAttributeRoutingConfig, ...rest } = props;
|
||||
|
||||
// There can be apps with no matching component
|
||||
if (!componentMap[slug]) return null;
|
||||
|
||||
const Component = componentMap[slug];
|
||||
|
||||
return (
|
||||
<div className={wrapperClassName || ""}>
|
||||
<Component
|
||||
appData={appData}
|
||||
route={route}
|
||||
setAttributeRoutingConfig={setAttributeRoutingConfig}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -40,7 +40,10 @@ export const getServerSidePropsForSingleFormView = async function getServerSideP
|
||||
const isFormCreateEditAllowed = (await import("../lib/isFormCreateEditAllowed")).isFormCreateEditAllowed;
|
||||
if (!(await isFormCreateEditAllowed({ userId: user.id, formId, targetTeamId: null }))) {
|
||||
return {
|
||||
notFound: true,
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination: "/403",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const ROUTING_FORM_RESPONSE_ID_QUERY_STRING = "cal.routingFormResponseId";
|
||||
@@ -0,0 +1,2 @@
|
||||
/** This is a list of apps which have functionality in routing forms */
|
||||
export const enabledAppSlugs = ["salesforce"];
|
||||
@@ -0,0 +1,26 @@
|
||||
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { enabledAppSlugs } from "./enabledApps";
|
||||
import type { Prisma } from ".prisma/client";
|
||||
|
||||
const getEventTypeAppMetadata = (metadata: Prisma.JsonValue) => {
|
||||
const eventTypeMetadataParse = EventTypeMetaDataSchema.safeParse(metadata);
|
||||
|
||||
if (!eventTypeMetadataParse.success || !eventTypeMetadataParse.data) return;
|
||||
|
||||
const appMetadata = eventTypeMetadataParse.data.apps;
|
||||
|
||||
const eventTypeAppMetadata: Record<string, any> = {};
|
||||
|
||||
if (appMetadata) {
|
||||
for (const appSlug of Object.keys(appMetadata)) {
|
||||
if (enabledAppSlugs.includes(appSlug)) {
|
||||
eventTypeAppMetadata[appSlug] = appMetadata[appSlug as keyof typeof appMetadata];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eventTypeAppMetadata;
|
||||
};
|
||||
|
||||
export default getEventTypeAppMetadata;
|
||||
@@ -22,11 +22,6 @@ export async function isFormCreateEditAllowed({
|
||||
select: {
|
||||
userId: true,
|
||||
teamId: true,
|
||||
team: {
|
||||
select: {
|
||||
members: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -37,5 +32,5 @@ export async function isFormCreateEditAllowed({
|
||||
});
|
||||
}
|
||||
|
||||
return canEditEntity(form, userId);
|
||||
return await canEditEntity(form, userId);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user