Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afc738141f | ||
|
|
efa195059e | ||
|
|
0f2b6bbe1a | ||
|
|
28b94a865f | ||
|
|
f45803fcfa | ||
|
|
053da1ec32 | ||
|
|
f0dcfc83c8 | ||
|
|
5eb3af54b3 | ||
|
|
3552bbc6cf | ||
|
|
028bd77c91 | ||
|
|
65a1aa6100 | ||
|
|
a09401c203 | ||
|
|
7c23773636 | ||
|
|
56ba8c0a07 | ||
|
|
5924bc0990 | ||
|
+27 |
10ffd9bacd | ||
|
|
20c45b5d88 | ||
|
|
3cab37ed8d | ||
|
|
98799b50f0 | ||
|
|
8071016848 | ||
|
|
aa5e2ac9a5 | ||
|
|
06857a4a69 | ||
|
|
b0d1720d92 | ||
|
|
e148ee7823 | ||
|
|
bb9a039931 | ||
|
|
053f93ea0a | ||
|
|
2a982c6b6d | ||
|
|
85490fef4d | ||
|
|
57afd7a2b1 | ||
|
|
0f9c3571fe | ||
|
|
1b3f676e57 | ||
|
|
3e17b1c5ef | ||
|
|
a466e71d4c | ||
|
|
5a7030d277 | ||
|
|
e72c25f02e | ||
|
|
06bc5facf3 | ||
|
|
9c8dc1b92c | ||
|
|
cfef92a7bc | ||
|
|
26149e2b04 | ||
|
|
3ca43ce3f3 | ||
|
|
7603ea6184 | ||
|
|
9c45da565e | ||
|
|
f84f1f5dda | ||
|
|
07f803e758 | ||
|
|
268ab882cd | ||
|
|
8052e6f6d4 | ||
|
|
99e9425257 | ||
|
|
471b2687c4 | ||
|
|
9f7152c4eb | ||
|
|
e819a31dd6 | ||
|
|
8356cb7d34 | ||
|
|
ceb18167cf | ||
|
|
4d5697f5a5 | ||
|
|
afe180a0ec | ||
|
|
851a388853 | ||
|
|
07e20144df | ||
|
|
1535e48ce5 | ||
|
|
0dce391f46 | ||
|
|
cfe7ea45ec | ||
|
|
c244f0fc8e | ||
|
|
5301af2e9f | ||
|
|
a4e7ca91b5 | ||
|
|
64e6e1a19a | ||
|
|
a6daf17909 | ||
|
|
c7dfa7bc89 | ||
|
|
633d85e81b | ||
|
|
49a61207d5 | ||
|
|
f3eb490e3b | ||
|
|
2de5f57437 | ||
|
|
8bdd835a68 | ||
|
|
9c7d0ea604 | ||
|
|
a3aa53fe6e | ||
|
|
57384eb921 | ||
|
|
a153f9627d | ||
|
|
a54539d211 | ||
|
|
8d736cfb67 | ||
|
|
3c3564f884 | ||
|
|
cc75899b01 | ||
|
|
1a818ab0c3 | ||
|
|
7dafaf1381 | ||
|
|
74f354abd2 | ||
|
|
f281131bf6 | ||
|
|
22b4bcdeeb | ||
|
|
5f59ef2acf | ||
|
|
d6d4e246f9 | ||
|
|
a49c34e733 | ||
|
|
37ce8860b5 | ||
|
|
4dfbc46247 | ||
|
|
4c38ea3329 | ||
|
|
24e60498f4 | ||
|
|
fa9a8cca89 | ||
|
|
38bb01a9f0 | ||
|
|
3cf6fef159 | ||
|
|
26dac453e9 | ||
|
|
52db023f76 | ||
|
|
df9e02d138 | ||
|
|
d7be40f67b | ||
|
|
68d2a97e92 | ||
|
|
cde9b24a9b | ||
|
|
cf89598279 | ||
|
|
fcd892bfa0 | ||
|
|
bee5011ec1 |
No files matched your search
@@ -215,3 +215,8 @@ PROJECT_ID_VERCEL=
|
|||||||
TEAM_ID_VERCEL=
|
TEAM_ID_VERCEL=
|
||||||
# Get it from: https://vercel.com/account/tokens
|
# Get it from: https://vercel.com/account/tokens
|
||||||
AUTH_BEARER_TOKEN_VERCEL=
|
AUTH_BEARER_TOKEN_VERCEL=
|
||||||
|
|
||||||
|
# - APPLE CALENDAR
|
||||||
|
# Used for E2E tests on Apple Calendar
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL=""
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD=""
|
||||||
@@ -5,16 +5,15 @@ on:
|
|||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
label_on_pr:
|
label_on_pr:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: none
|
contents: none
|
||||||
issues: read
|
issues: read
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Apply labels from linked issue to PR
|
- name: Apply labels from linked issue to PR
|
||||||
uses: actions/github-script@v5
|
uses: actions/github-script@v5
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# .github/workflows/chromatic.yml
|
# .github/workflows/chromatic.yml
|
||||||
|
|
||||||
# Workflow name
|
# Workflow name
|
||||||
name: 'Chromatic'
|
name: "Chromatic"
|
||||||
|
|
||||||
# Event for the workflow
|
# Event for the workflow
|
||||||
on:
|
on:
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ jobs:
|
|||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ jobs:
|
|||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ jobs:
|
|||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
|
|||||||
@@ -40,11 +40,13 @@ jobs:
|
|||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }}
|
EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }}
|
||||||
EMAIL_SERVER_PORT: ${{ secrets.CI_EMAIL_SERVER_PORT }}
|
EMAIL_SERVER_PORT: ${{ secrets.CI_EMAIL_SERVER_PORT }}
|
||||||
EMAIL_SERVER_USER: ${{ secrets.CI_EMAIL_SERVER_USER }}
|
EMAIL_SERVER_USER: ${{ secrets.CI_EMAIL_SERVER_USER }}
|
||||||
EMAIL_SERVER_PASSWORD: ${{ secrets.CI_EMAIL_SERVER_PASSWORD}}
|
EMAIL_SERVER_PASSWORD: ${{ secrets.CI_EMAIL_SERVER_PASSWORD}}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
NEXTAUTH_URL: ${{ secrets.CI_NEXTAUTH_URL }}
|
NEXTAUTH_URL: ${{ secrets.CI_NEXTAUTH_URL }}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ env:
|
|||||||
ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }}
|
ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }}
|
||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ env:
|
|||||||
ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }}
|
ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }}
|
||||||
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
|
||||||
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
DATABASE_URL: ${{ secrets.CI_DATABASE_URL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }}
|
||||||
|
E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }}
|
||||||
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
|
||||||
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }}
|
||||||
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ on: # yamllint disable-line rule:truthy
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
RELEASE_TAG:
|
RELEASE_TAG:
|
||||||
description: 'v{Major}.{Minor}.{Patch}'
|
description: "v{Major}.{Minor}.{Patch}"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Determine tag"
|
- name: "Determine tag"
|
||||||
run: "echo \"RELEASE_TAG=${GITHUB_REF#refs/tags/}\" >> $GITHUB_ENV"
|
run: 'echo "RELEASE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV'
|
||||||
|
|
||||||
- name: "Run remote release workflow"
|
- name: "Run remote release workflow"
|
||||||
uses: "actions/github-script@v6"
|
uses: "actions/github-script@v6"
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ jobs:
|
|||||||
header: pr-title-lint-error
|
header: pr-title-lint-error
|
||||||
message: |
|
message: |
|
||||||
Hey there and thank you for opening this pull request! 👋🏼
|
Hey there and thank you for opening this pull request! 👋🏼
|
||||||
|
|
||||||
We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
|
We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
|
||||||
|
|
||||||
Details:
|
Details:
|
||||||
|
|
||||||
```
|
```
|
||||||
${{ steps.lint_pr_title.outputs.error_message }}
|
${{ steps.lint_pr_title.outputs.error_message }}
|
||||||
```
|
```
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
# Delete a previous comment when the issue has been resolved
|
# Delete a previous comment when the issue has been resolved
|
||||||
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
|
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
|
||||||
uses: marocchino/sticky-pull-request-comment@v2
|
uses: marocchino/sticky-pull-request-comment@v2
|
||||||
with:
|
with:
|
||||||
header: pr-title-lint-error
|
header: pr-title-lint-error
|
||||||
message: |
|
message: |
|
||||||
Thank you for following the naming conventions! 🙏
|
Thank you for following the naming conventions! 🙏
|
||||||
+1
-1
@@ -40,4 +40,4 @@ vscode:
|
|||||||
- bradlc.vscode-tailwindcss
|
- bradlc.vscode-tailwindcss
|
||||||
- ban.spellright
|
- ban.spellright
|
||||||
- stripe.vscode-stripe
|
- stripe.vscode-stripe
|
||||||
- Prisma.prisma
|
- Prisma.prisma
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
# Scheduling infrastructure for absolutely everyone
|
# Scheduling infrastructure for absolutely everyone
|
||||||
|
|
||||||
The open source Calendly alternative. You are in charge
|
The open source Calendly alternative. You are in charge
|
||||||
of your own data, workflow and appearance.
|
of your own data, workflow, and appearance.
|
||||||
|
|
||||||
Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes and even calls with our families. However, most tools are very limited in terms of control and customizations.
|
Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes, and even calls with our families. However, most tools are very limited in terms of control and customization.
|
||||||
|
|
||||||
That's where Cal.com comes in. Self-hosted or hosted by us. White-label by design. API-driven and ready to be deployed on your own domain. Full control of your events and data.
|
That's where Cal.com comes in. Self-hosted or hosted by us. White-label by design. API-driven and ready to be deployed on your own domain. Full control of your events and data.
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ Meet our sales team for any commercial inquiries.
|
|||||||
|
|
||||||
## Stay Up-to-Date
|
## Stay Up-to-Date
|
||||||
|
|
||||||
Cal.com officially launched as v.1.0 on 15th of September 2021 and we've come a long way so far. Watch **releases** of this repository to be notified of future updates:
|
Cal.com officially launched as v.1.0 on the 15th of September 2021 and we've come a long way so far. Watch **releases** of this repository to be notified of future updates:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ Here is what you need to be able to run Cal.com.
|
|||||||
git clone https://github.com/calcom/cal.com.git
|
git clone https://github.com/calcom/cal.com.git
|
||||||
```
|
```
|
||||||
|
|
||||||
> If you are on windows, run the following command on `gitbash` with admin privileges: <br> > `git clone -c core.symlinks=true https://github.com/calcom/cal.com.git` <br>
|
> If you are on Windows, run the following command on `gitbash` with admin privileges: <br> > `git clone -c core.symlinks=true https://github.com/calcom/cal.com.git` <br>
|
||||||
> See [docs](https://cal.com/docs/how-to-guides/how-to-troubleshoot-symbolic-link-issues-on-windows#enable-symbolic-links) for more details.
|
> See [docs](https://cal.com/docs/how-to-guides/how-to-troubleshoot-symbolic-link-issues-on-windows#enable-symbolic-links) for more details.
|
||||||
|
|
||||||
1. Go to the project folder
|
1. Go to the project folder
|
||||||
@@ -254,7 +254,7 @@ Be sure to set the environment variable `NEXTAUTH_URL` to the correct value. If
|
|||||||
# In a terminal just run:
|
# In a terminal just run:
|
||||||
yarn test-e2e
|
yarn test-e2e
|
||||||
|
|
||||||
# To open last HTML report run:
|
# To open the last HTML report run:
|
||||||
yarn playwright show-report test-results/reports/playwright-html-report
|
yarn playwright show-report test-results/reports/playwright-html-report
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { NextMiddleware } from "next-api-middleware";
|
|||||||
|
|
||||||
import { hashAPIKey } from "@calcom/features/ee/api-keys/lib/apiKeys";
|
import { hashAPIKey } from "@calcom/features/ee/api-keys/lib/apiKeys";
|
||||||
import checkLicense from "@calcom/features/ee/common/server/checkLicense";
|
import checkLicense from "@calcom/features/ee/common/server/checkLicense";
|
||||||
|
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||||
|
|
||||||
import { isAdminGuard } from "~/lib/utils/isAdmin";
|
import { isAdminGuard } from "~/lib/utils/isAdmin";
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ export const dateNotInPast = function (date: Date) {
|
|||||||
export const verifyApiKey: NextMiddleware = async (req, res, next) => {
|
export const verifyApiKey: NextMiddleware = async (req, res, next) => {
|
||||||
const { prisma, isCustomPrisma, isAdmin } = req;
|
const { prisma, isCustomPrisma, isAdmin } = req;
|
||||||
const hasValidLicense = await checkLicense(prisma);
|
const hasValidLicense = await checkLicense(prisma);
|
||||||
if (!hasValidLicense && process.env.NODE_ENV !== "development")
|
if (!hasValidLicense && IS_PRODUCTION)
|
||||||
return res.status(401).json({ error: "Invalid or missing CALCOM_LICENSE_KEY environment variable" });
|
return res.status(401).json({ error: "Invalid or missing CALCOM_LICENSE_KEY environment variable" });
|
||||||
// If the user is an admin and using a license key (from customPrisma), skip the apiKey check.
|
// If the user is an admin and using a license key (from customPrisma), skip the apiKey check.
|
||||||
if (isCustomPrisma && isAdmin) {
|
if (isCustomPrisma && isAdmin) {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ const schemaEventTypeCreateParams = z
|
|||||||
seatsPerTimeSlot: z.number().optional(),
|
seatsPerTimeSlot: z.number().optional(),
|
||||||
seatsShowAttendees: z.boolean().optional(),
|
seatsShowAttendees: z.boolean().optional(),
|
||||||
bookingFields: eventTypeBookingFields.optional(),
|
bookingFields: eventTypeBookingFields.optional(),
|
||||||
|
scheduleId: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ const schemaEventTypeEditParams = z
|
|||||||
seatsPerTimeSlot: z.number().optional(),
|
seatsPerTimeSlot: z.number().optional(),
|
||||||
seatsShowAttendees: z.boolean().optional(),
|
seatsShowAttendees: z.boolean().optional(),
|
||||||
bookingFields: eventTypeBookingFields.optional(),
|
bookingFields: eventTypeBookingFields.optional(),
|
||||||
|
scheduleId: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
@@ -98,6 +100,7 @@ export const schemaEventTypeReadPublic = EventType.pick({
|
|||||||
position: true,
|
position: true,
|
||||||
userId: true,
|
userId: true,
|
||||||
teamId: true,
|
teamId: true,
|
||||||
|
scheduleId: true,
|
||||||
eventName: true,
|
eventName: true,
|
||||||
timeZone: true,
|
timeZone: true,
|
||||||
periodType: true,
|
periodType: true,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { NextApiRequest } from "next";
|
import type { NextApiRequest } from "next";
|
||||||
|
|
||||||
|
import { HttpError } from "@calcom/lib/http-error";
|
||||||
import { defaultResponder } from "@calcom/lib/server";
|
import { defaultResponder } from "@calcom/lib/server";
|
||||||
|
|
||||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||||
|
import { checkPermissions as canAccessTeamEventOrThrow } from "~/pages/api/teams/[teamId]/_auth-middleware";
|
||||||
|
|
||||||
import getCalLink from "../_utils/getCalLink";
|
import getCalLink from "../_utils/getCalLink";
|
||||||
|
|
||||||
@@ -42,7 +44,8 @@ import getCalLink from "../_utils/getCalLink";
|
|||||||
export async function getHandler(req: NextApiRequest) {
|
export async function getHandler(req: NextApiRequest) {
|
||||||
const { prisma, query } = req;
|
const { prisma, query } = req;
|
||||||
const { id } = schemaQueryIdParseInt.parse(query);
|
const { id } = schemaQueryIdParseInt.parse(query);
|
||||||
const event_type = await prisma.eventType.findUnique({
|
|
||||||
|
const eventType = await prisma.eventType.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: {
|
||||||
customInputs: true,
|
customInputs: true,
|
||||||
@@ -51,10 +54,43 @@ export async function getHandler(req: NextApiRequest) {
|
|||||||
owner: { select: { username: true, id: true } },
|
owner: { select: { username: true, id: true } },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await checkPermissions(req, eventType);
|
||||||
|
|
||||||
const link = event_type ? getCalLink(event_type) : null;
|
const link = eventType ? getCalLink(eventType) : null;
|
||||||
|
// user.defaultScheduleId doesn't work the same for team events.
|
||||||
|
if (!eventType?.scheduleId && eventType?.userId && !eventType?.teamId) {
|
||||||
|
const user = await prisma.user.findUniqueOrThrow({
|
||||||
|
where: {
|
||||||
|
id: eventType.userId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
defaultScheduleId: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
eventType.scheduleId = user.defaultScheduleId;
|
||||||
|
}
|
||||||
|
|
||||||
return { event_type: schemaEventTypeReadPublic.parse({ ...event_type, link }) };
|
// TODO: eventType when not found should be a 404
|
||||||
|
// but API consumers may depend on the {} behaviour.
|
||||||
|
return { event_type: schemaEventTypeReadPublic.parse({ ...eventType, link }) };
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseEventTypeCheckPermissions = {
|
||||||
|
userId: number | null;
|
||||||
|
teamId: number | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function checkPermissions<T extends BaseEventTypeCheckPermissions>(
|
||||||
|
req: NextApiRequest,
|
||||||
|
eventType: (T & Partial<Omit<T, keyof BaseEventTypeCheckPermissions>>) | null
|
||||||
|
) {
|
||||||
|
if (req.isAdmin) return true;
|
||||||
|
if (eventType?.teamId) {
|
||||||
|
req.query.teamId = String(eventType.teamId);
|
||||||
|
await canAccessTeamEventOrThrow(req, "MEMBER");
|
||||||
|
}
|
||||||
|
if (eventType?.userId === req.userId) return true; // is owner.
|
||||||
|
throw new HttpError({ statusCode: 403, message: "Forbidden" });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defaultResponder(getHandler);
|
export default defaultResponder(getHandler);
|
||||||
@@ -52,6 +52,9 @@ import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission
|
|||||||
* slug:
|
* slug:
|
||||||
* type: string
|
* type: string
|
||||||
* description: Unique slug for the event type
|
* description: Unique slug for the event type
|
||||||
|
* scheduleId:
|
||||||
|
* type: number
|
||||||
|
* description: The ID of the schedule for this event type
|
||||||
* hosts:
|
* hosts:
|
||||||
* type: array
|
* type: array
|
||||||
* items:
|
* items:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { Prisma } from "@prisma/client";
|
|
||||||
import type { NextApiRequest } from "next";
|
import type { NextApiRequest } from "next";
|
||||||
|
|
||||||
import { HttpError } from "@calcom/lib/http-error";
|
import { HttpError } from "@calcom/lib/http-error";
|
||||||
import { defaultResponder } from "@calcom/lib/server";
|
import { defaultResponder } from "@calcom/lib/server";
|
||||||
|
import type { PrismaClient } from "@calcom/prisma/client";
|
||||||
|
|
||||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||||
@@ -35,20 +35,12 @@ import getCalLink from "./_utils/getCalLink";
|
|||||||
* description: No event types were found
|
* description: No event types were found
|
||||||
*/
|
*/
|
||||||
async function getHandler(req: NextApiRequest) {
|
async function getHandler(req: NextApiRequest) {
|
||||||
const { userId, isAdmin, prisma } = req;
|
const { userId, prisma } = req;
|
||||||
|
const userIds = req.query.userId ? extractUserIdsFromQuery(req) : [userId];
|
||||||
const args: Prisma.EventTypeFindManyArgs = {
|
|
||||||
where: { userId },
|
|
||||||
};
|
|
||||||
/** Only admins can query other users */
|
|
||||||
if (!isAdmin && req.query.userId) throw new HttpError({ statusCode: 401, message: "ADMIN required" });
|
|
||||||
if (isAdmin && req.query.userId) {
|
|
||||||
const query = schemaQuerySingleOrMultipleUserIds.parse(req.query);
|
|
||||||
const userIds = Array.isArray(query.userId) ? query.userId : [query.userId || userId];
|
|
||||||
args.where = { userId: { in: userIds } };
|
|
||||||
}
|
|
||||||
const data = await prisma.eventType.findMany({
|
const data = await prisma.eventType.findMany({
|
||||||
...args,
|
where: {
|
||||||
|
userId: { in: userIds },
|
||||||
|
},
|
||||||
include: {
|
include: {
|
||||||
customInputs: true,
|
customInputs: true,
|
||||||
team: { select: { slug: true } },
|
team: { select: { slug: true } },
|
||||||
@@ -56,13 +48,74 @@ async function getHandler(req: NextApiRequest) {
|
|||||||
owner: { select: { username: true, id: true } },
|
owner: { select: { username: true, id: true } },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// this really should return [], but backwards compatibility..
|
||||||
if (data.length === 0) new HttpError({ statusCode: 404, message: "No event types were found" });
|
if (data.length === 0) new HttpError({ statusCode: 404, message: "No event types were found" });
|
||||||
return {
|
return {
|
||||||
event_types: data.map((eventType) => {
|
event_types: (await defaultScheduleId<(typeof data)[number]>({ eventTypes: data, prisma, userIds })).map(
|
||||||
const link = getCalLink(eventType);
|
(eventType) => {
|
||||||
return schemaEventTypeReadPublic.parse({ ...eventType, link });
|
const link = getCalLink(eventType);
|
||||||
}),
|
return schemaEventTypeReadPublic.parse({ ...eventType, link });
|
||||||
|
}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// TODO: Extract & reuse.
|
||||||
|
function extractUserIdsFromQuery({ isAdmin, query }: NextApiRequest) {
|
||||||
|
/** Guard: Only admins can query other users */
|
||||||
|
if (!isAdmin) {
|
||||||
|
throw new HttpError({ statusCode: 401, message: "ADMIN required" });
|
||||||
|
}
|
||||||
|
const { userId: userIdOrUserIds } = schemaQuerySingleOrMultipleUserIds.parse(query);
|
||||||
|
return Array.isArray(userIdOrUserIds) ? userIdOrUserIds : [userIdOrUserIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultScheduleIdEventTypeBase = {
|
||||||
|
scheduleId: number | null;
|
||||||
|
userId: number | null;
|
||||||
|
};
|
||||||
|
// If an eventType is given w/o a scheduleId
|
||||||
|
// Then we associate the default user schedule id to the eventType
|
||||||
|
async function defaultScheduleId<T extends DefaultScheduleIdEventTypeBase>({
|
||||||
|
prisma,
|
||||||
|
eventTypes,
|
||||||
|
userIds,
|
||||||
|
}: {
|
||||||
|
prisma: PrismaClient;
|
||||||
|
eventTypes: (T & Partial<Omit<T, keyof DefaultScheduleIdEventTypeBase>>)[];
|
||||||
|
userIds: number[];
|
||||||
|
}) {
|
||||||
|
// there is no event types without a scheduleId, skip the user query
|
||||||
|
if (eventTypes.every((eventType) => eventType.scheduleId)) return eventTypes;
|
||||||
|
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: userIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
defaultScheduleId: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!users.length) {
|
||||||
|
return eventTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultScheduleIds = users.reduce((result, user) => {
|
||||||
|
result[user.id] = user.defaultScheduleId;
|
||||||
|
return result;
|
||||||
|
}, {} as { [x: number]: number | null });
|
||||||
|
|
||||||
|
return eventTypes.map((eventType) => {
|
||||||
|
// realistically never happens, userId should't be null on personal event types.
|
||||||
|
if (!eventType.userId) return eventType;
|
||||||
|
return {
|
||||||
|
...eventType,
|
||||||
|
scheduleId: eventType.scheduleId || defaultScheduleIds[eventType.userId],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default defaultResponder(getHandler);
|
export default defaultResponder(getHandler);
|
||||||
@@ -60,6 +60,9 @@ import ensureOnlyMembersAsHosts from "./_utils/ensureOnlyMembersAsHosts";
|
|||||||
* hidden:
|
* hidden:
|
||||||
* type: boolean
|
* type: boolean
|
||||||
* description: If the event type should be hidden from your public booking page
|
* description: If the event type should be hidden from your public booking page
|
||||||
|
* scheduleId:
|
||||||
|
* type: number
|
||||||
|
* description: The ID of the schedule for this event type
|
||||||
* position:
|
* position:
|
||||||
* type: integer
|
* type: integer
|
||||||
* description: The position of the event type on the public booking page
|
* description: The position of the event type on the public booking page
|
||||||
@@ -178,6 +181,7 @@ import ensureOnlyMembersAsHosts from "./_utils/ensureOnlyMembersAsHosts";
|
|||||||
* position: 0
|
* position: 0
|
||||||
* eventName: null
|
* eventName: null
|
||||||
* timeZone: null
|
* timeZone: null
|
||||||
|
* scheduleId: 5
|
||||||
* periodType: UNLIMITED
|
* periodType: UNLIMITED
|
||||||
* periodStartDate: 2023-02-15T08:46:16.000Z
|
* periodStartDate: 2023-02-15T08:46:16.000Z
|
||||||
* periodEndDate: 2023-0-15T08:46:16.000Z
|
* periodEndDate: 2023-0-15T08:46:16.000Z
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ async function getHandler(req: NextApiRequest) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const data = await prisma.eventType.findMany(args);
|
const data = await prisma.eventType.findMany(args);
|
||||||
return { event_types: data.map((attendee) => schemaEventTypeReadPublic.parse(attendee)) };
|
return { event_types: data.map((eventType) => schemaEventTypeReadPublic.parse(eventType)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defaultResponder(getHandler);
|
export default defaultResponder(getHandler);
|
||||||
@@ -40,7 +40,7 @@ export async function getHandler(req: NextApiRequest) {
|
|||||||
// If user is not ADMIN, return only his data.
|
// If user is not ADMIN, return only his data.
|
||||||
if (!isAdmin) where.id = userId;
|
if (!isAdmin) where.id = userId;
|
||||||
const [total, data] = await prisma.$transaction([
|
const [total, data] = await prisma.$transaction([
|
||||||
prisma.user.count(),
|
prisma.user.count({ where }),
|
||||||
prisma.user.findMany({ where, take, skip }),
|
prisma.user.findMany({ where, take, skip }),
|
||||||
]);
|
]);
|
||||||
const users = schemaUsersReadPublic.parse(data);
|
const users = schemaUsersReadPublic.parse(data);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Set the version of docker compose to use
|
# Set the version of docker compose to use
|
||||||
version: '3.9'
|
version: "3.9"
|
||||||
|
|
||||||
# The containers that compose the project
|
# The containers that compose the project
|
||||||
services:
|
services:
|
||||||
@@ -8,8 +8,8 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
container_name: integration-tests-prisma
|
container_name: integration-tests-prisma
|
||||||
ports:
|
ports:
|
||||||
- '5433:5432'
|
- "5433:5432"
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: prisma
|
POSTGRES_USER: prisma
|
||||||
POSTGRES_PASSWORD: prisma
|
POSTGRES_PASSWORD: prisma
|
||||||
POSTGRES_DB: tests
|
POSTGRES_DB: tests
|
||||||
@@ -15,6 +15,7 @@ module.exports = {
|
|||||||
"storybook-addon-rtl-direction",
|
"storybook-addon-rtl-direction",
|
||||||
"storybook-react-i18next",
|
"storybook-react-i18next",
|
||||||
"storybook-addon-next",
|
"storybook-addon-next",
|
||||||
|
"storybook-addon-next-router",
|
||||||
/*{
|
/*{
|
||||||
name: "storybook-addon-next",
|
name: "storybook-addon-next",
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
window.global = window;
|
window.global = window;
|
||||||
window.isEmbed = ()=> {
|
window.isEmbed = () => {
|
||||||
return location.search.includes("embed=")
|
return location.search.includes("embed=");
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500&display=swap');
|
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@500&display=swap");
|
||||||
</style>
|
</style>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { addDecorator } from "@storybook/react";
|
import { addDecorator } from "@storybook/react";
|
||||||
|
import { AppRouterContext } from "next/dist/shared/lib/app-router-context";
|
||||||
import { I18nextProvider } from "react-i18next";
|
import { I18nextProvider } from "react-i18next";
|
||||||
|
|
||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
@@ -13,6 +14,13 @@ export const parameters = {
|
|||||||
date: /Date$/,
|
date: /Date$/,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
nextRouter: {
|
||||||
|
pathname: "/",
|
||||||
|
asPath: "/",
|
||||||
|
query: {},
|
||||||
|
push() {},
|
||||||
|
Provider: AppRouterContext.Provider,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
addDecorator((storyFn) => (
|
addDecorator((storyFn) => (
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
import { Meta } from '@storybook/addon-docs';
|
import { Meta } from "@storybook/addon-docs";
|
||||||
|
|
||||||
<Meta title="Introduction" />
|
<Meta title="Introduction" />
|
||||||
|
|
||||||
<div className="text-center flex flex-col items-center">
|
<div className="flex flex-col items-center text-center">
|
||||||
<h1 style={{marginBottom: '24px', marginTop: '36px'}}>Welcome to Cal.com UI</h1>
|
<h1 style={{ marginBottom: "24px", marginTop: "36px" }}>Welcome to Cal.com UI</h1>
|
||||||
<p>This is the beginning of our storybook improvements to match Figma as close as possible. Like our Figma library, we will be adding more components as we go along.</p>
|
<p>
|
||||||
<p>Our <a href="https://www.figma.com/file/9MOufQNLtdkpnDucmNX10R/%E2%9D%96-Cal-DS" target="_blank">Figma</a> library is avalible for anyone to view and use. If you have any questions or concerns, please reach out to the design team.</p>
|
This is the beginning of our storybook improvements to match Figma as close as possible. Like our Figma
|
||||||
|
library, we will be adding more components as we go along.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Our{" "}
|
||||||
|
<a href="https://www.figma.com/file/9MOufQNLtdkpnDucmNX10R/%E2%9D%96-Cal-DS" target="_blank">
|
||||||
|
Figma
|
||||||
|
</a>{" "}
|
||||||
|
library is avalible for anyone to view and use. If you have any questions or concerns, please reach out to
|
||||||
|
the design team.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img src="/sb-cover.jpg" />
|
<img src="/sb-cover.jpg" />
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
"next": "^13.4.6",
|
"next": "^13.4.6",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"storybook-addon-next-router": "^4.0.2",
|
||||||
"storybook-addon-rtl-direction": "^0.0.19"
|
"storybook-addon-rtl-direction": "^0.0.19"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@import url("../../../packages/features/calendars/weeklyview/styles/styles.css");
|
@import url("../../../packages/features/calendars/weeklyview/styles/styles.css");
|
||||||
|
|
||||||
.sbdocs {
|
.sbdocs {
|
||||||
font-family: 'Inter var' !important;
|
font-family: "Inter var" !important;
|
||||||
padding: 0!important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#docs-root {
|
#docs-root {
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(0, 0, 0, 0.12);
|
border-top: 2px solid rgba(0, 0, 0, 0.12);
|
||||||
padding-top: 12px!important;
|
padding-top: 12px !important;
|
||||||
padding-bottom: 12px!important;
|
padding-bottom: 12px !important;
|
||||||
margin: 82px 0 0 0;
|
margin: 82px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Docs table **/
|
/** Docs table **/
|
||||||
.custom-args-wrapper{
|
.custom-args-wrapper {
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.docblock-argstable-body {
|
.docblock-argstable-body {
|
||||||
box-shadow: none!important;
|
box-shadow: none !important;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
.docblock-argstable-body div p,
|
.docblock-argstable-body div p,
|
||||||
.docblock-argstable-body div span {
|
.docblock-argstable-body div span {
|
||||||
color: #8F8F8F !important;
|
color: #8f8f8f !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Custom components **/
|
/** Custom components **/
|
||||||
@@ -83,8 +83,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.story-title h1 span {
|
.story-title h1 span {
|
||||||
color: #9CA3AF;
|
color: #9ca3af;
|
||||||
font-family: 'Inter var';
|
font-family: "Inter var";
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.examples {
|
.examples {
|
||||||
background-color: #F9FAFB;
|
background-color: #f9fafb;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -111,14 +111,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.examples-title {
|
.examples-title {
|
||||||
color: #8F8F8F;
|
color: #8f8f8f;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.examples-item-title {
|
.examples-item-title {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #8F8F8F;
|
color: #8f8f8f;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
.examples-footnote p,
|
.examples-footnote p,
|
||||||
.examples-footnote ul,
|
.examples-footnote ul,
|
||||||
.examples-footnote li {
|
.examples-footnote li {
|
||||||
color: #8F8F8F;
|
color: #8f8f8f;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,11 +139,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.examples-footnote li {
|
.examples-footnote li {
|
||||||
margin: 0!important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.story-note {
|
.story-note {
|
||||||
background-color: #F9FAFB;
|
background-color: #f9fafb;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@@ -161,12 +161,12 @@
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
border-radius: none!important;
|
border-radius: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-story > div:first-child {
|
.docs-story > div:first-child {
|
||||||
padding: 0!important;
|
padding: 0 !important;
|
||||||
margin: 0!important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-story .innerZoomElementWrapper > div {
|
.docs-story .innerZoomElementWrapper > div {
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sb-main-padded {
|
.sb-main-padded {
|
||||||
padding: 0!important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1200px) {
|
@media screen and (max-width: 1200px) {
|
||||||
@@ -198,74 +198,72 @@
|
|||||||
:root {
|
:root {
|
||||||
/* background */
|
/* background */
|
||||||
|
|
||||||
--cal-bg-emphasis: #E5E7EB;
|
--cal-bg-emphasis: #e5e7eb;
|
||||||
--cal-bg: white;
|
--cal-bg: white;
|
||||||
--cal-bg-subtle: #F3F4F6;
|
--cal-bg-subtle: #f3f4f6;
|
||||||
--cal-bg-muted: #F9FAFB;
|
--cal-bg-muted: #f9fafb;
|
||||||
--cal-bg-inverted: #111827;
|
--cal-bg-inverted: #111827;
|
||||||
|
|
||||||
/* background -> components*/
|
/* background -> components*/
|
||||||
--cal-bg-info: #DEE9FC;
|
--cal-bg-info: #dee9fc;
|
||||||
--cal-bg-success: #E2FBE8;
|
--cal-bg-success: #e2fbe8;
|
||||||
--cal-bg-attention: #FCEED8;
|
--cal-bg-attention: #fceed8;
|
||||||
--cal-bg-error: #F9E3E2;
|
--cal-bg-error: #f9e3e2;
|
||||||
--cal-bg-dark-error: #752522;
|
--cal-bg-dark-error: #752522;
|
||||||
|
|
||||||
|
|
||||||
/* Borders */
|
/* Borders */
|
||||||
--cal-border-emphasis:#9CA3AF;
|
--cal-border-emphasis: #9ca3af;
|
||||||
--cal-border: #D1D5DB;
|
--cal-border: #d1d5db;
|
||||||
--cal-border-subtle:#E5E7EB;
|
--cal-border-subtle: #e5e7eb;
|
||||||
--cal-border-muted:#F3F4F6;
|
--cal-border-muted: #f3f4f6;
|
||||||
--cal-border-error: #aa2e26;
|
--cal-border-error: #aa2e26;
|
||||||
|
|
||||||
/* Content/Text */
|
/* Content/Text */
|
||||||
--cal-text-emphasis: #111827;
|
--cal-text-emphasis: #111827;
|
||||||
--cal-text:#374151;
|
--cal-text: #374151;
|
||||||
--cal-text-subtle:#6B7280;
|
--cal-text-subtle: #6b7280;
|
||||||
--cal-text-muted:#9CA3AF;
|
--cal-text-muted: #9ca3af;
|
||||||
--cal-text-inverted:white;
|
--cal-text-inverted: white;
|
||||||
|
|
||||||
/* Content/Text -> components */
|
/* Content/Text -> components */
|
||||||
--cal-text-info:#253985;
|
--cal-text-info: #253985;
|
||||||
--cal-text-success:#285231;
|
--cal-text-success: #285231;
|
||||||
--cal-text-attention:#73321B;
|
--cal-text-attention: #73321b;
|
||||||
--cal-text-error:#752522;
|
--cal-text-error: #752522;
|
||||||
|
|
||||||
/* Brand shinanigans
|
/* Brand shinanigans
|
||||||
-> These will be computed for the users theme at runtime.
|
-> These will be computed for the users theme at runtime.
|
||||||
*/
|
*/
|
||||||
--cal-brand:#111827;
|
--cal-brand: #111827;
|
||||||
--cal-brand-emphasis:#101010;
|
--cal-brand-emphasis: #101010;
|
||||||
--cal-brand-text: white;
|
--cal-brand-text: white;
|
||||||
}
|
}
|
||||||
.dark {
|
.dark {
|
||||||
/* background */
|
/* background */
|
||||||
|
|
||||||
--cal-bg-emphasis: #2B2B2B;
|
--cal-bg-emphasis: #2b2b2b;
|
||||||
--cal-bg: #101010;
|
--cal-bg: #101010;
|
||||||
--cal-bg-subtle: #2B2B2B;
|
--cal-bg-subtle: #2b2b2b;
|
||||||
--cal-bg-muted: #1C1C1C;
|
--cal-bg-muted: #1c1c1c;
|
||||||
--cal-bg-inverted: #F3F4F6;
|
--cal-bg-inverted: #f3f4f6;
|
||||||
|
|
||||||
/* background -> components*/
|
/* background -> components*/
|
||||||
--cal-bg-info: #DEE9FC;
|
--cal-bg-info: #dee9fc;
|
||||||
--cal-bg-success: #E2FBE8;
|
--cal-bg-success: #e2fbe8;
|
||||||
--cal-bg-attention: #FCEED8;
|
--cal-bg-attention: #fceed8;
|
||||||
--cal-bg-error: #F9E3E2;
|
--cal-bg-error: #f9e3e2;
|
||||||
--cal-bg-dark-error: #752522;
|
--cal-bg-dark-error: #752522;
|
||||||
|
|
||||||
|
|
||||||
/* Borders */
|
/* Borders */
|
||||||
--cal-border-emphasis: #575757;
|
--cal-border-emphasis: #575757;
|
||||||
--cal-border: #444444;
|
--cal-border: #444444;
|
||||||
--cal-border-subtle: #2B2B2B;
|
--cal-border-subtle: #2b2b2b;
|
||||||
--cal-border-muted: #1C1C1C;
|
--cal-border-muted: #1c1c1c;
|
||||||
--cal-border-error: #aa2e26;
|
--cal-border-error: #aa2e26;
|
||||||
|
|
||||||
/* Content/Text */
|
/* Content/Text */
|
||||||
--cal-text-emphasis: #F3F4F6;
|
--cal-text-emphasis: #f3f4f6;
|
||||||
--cal-text: #D6D6D6;
|
--cal-text: #d6d6d6;
|
||||||
--cal-text-subtle: #757575;
|
--cal-text-subtle: #757575;
|
||||||
--cal-text-muted: #575757;
|
--cal-text-muted: #575757;
|
||||||
--cal-text-inverted: #101010;
|
--cal-text-inverted: #101010;
|
||||||
@@ -273,7 +271,7 @@
|
|||||||
/* Content/Text -> components */
|
/* Content/Text -> components */
|
||||||
--cal-text-info: #253985;
|
--cal-text-info: #253985;
|
||||||
--cal-text-success: #285231;
|
--cal-text-success: #285231;
|
||||||
--cal-text-attention: #73321B;
|
--cal-text-attention: #73321b;
|
||||||
--cal-text-error: #752522;
|
--cal-text-error: #752522;
|
||||||
|
|
||||||
/* Brand shenanigans
|
/* Brand shenanigans
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ html,
|
|||||||
body {
|
body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans,
|
||||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
Droid Sans, Helvetica Neue, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -21,7 +21,7 @@ a {
|
|||||||
}
|
}
|
||||||
.swagger-ui .opblock .opblock-summary {
|
.swagger-ui .opblock .opblock-summary {
|
||||||
display: grid;
|
display: grid;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.opblock-summary-path {
|
.opblock-summary-path {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -43,22 +43,22 @@ a {
|
|||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
.swagger-ui .scheme-container {
|
.swagger-ui .scheme-container {
|
||||||
padding: 14px 0;
|
padding: 14px 0;
|
||||||
}
|
}
|
||||||
.swagger-ui .info {
|
.swagger-ui .info {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
.swagger-ui .auth-wrapper {
|
.swagger-ui .auth-wrapper {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
.swagger-ui .authorization__btn {
|
.swagger-ui .authorization__btn {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.swagger-ui .opblock {
|
.swagger-ui .opblock {
|
||||||
margin: 0 0 5px;
|
margin: 0 0 5px;
|
||||||
}
|
}
|
||||||
button.opblock-summary-control > svg {
|
button.opblock-summary-control > svg {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.swagger-ui .filter .operation-filter-input {
|
.swagger-ui .filter .operation-filter-input {
|
||||||
border: 2px solid #d8dde7;
|
border: 2px solid #d8dde7;
|
||||||
@@ -73,15 +73,16 @@ a {
|
|||||||
.swagger-ui .info .title small {
|
.swagger-ui .info .title small {
|
||||||
top: 5px;
|
top: 5px;
|
||||||
}
|
}
|
||||||
.swagger-ui a.nostyle, .swagger-ui a.nostyle:visited {
|
.swagger-ui a.nostyle,
|
||||||
|
.swagger-ui a.nostyle:visited {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
div.request-snippets > div.curl-command > div:nth-child(1) {
|
div.request-snippets > div.curl-command > div:nth-child(1) {
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
.swagger-ui .opblock-body pre.microlight {
|
.swagger-ui .opblock-body pre.microlight {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
.swagger-ui table tbody tr td {
|
.swagger-ui table tbody tr td {
|
||||||
padding: 0px 0 0;
|
padding: 0px 0 0;
|
||||||
@@ -91,7 +92,7 @@ a {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
div.no-margin > div > div.responses-wrapper > div.responses-inner > div > div > table > tbody > tr {
|
div.no-margin > div > div.responses-wrapper > div.responses-inner > div > div > table > tbody > tr {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 60%;
|
font-size: 60%;
|
||||||
@@ -99,4 +100,4 @@ a {
|
|||||||
div.no-margin > div > div.responses-wrapper > div.responses-inner > div > div > table > thead > tr {
|
div.no-margin > div > div.responses-wrapper > div.responses-inner > div > div > table > thead > tr {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ export const InstallAppButtonChild = ({
|
|||||||
);
|
);
|
||||||
}}>
|
}}>
|
||||||
<p>
|
<p>
|
||||||
{team.name} {isInstalled && `(${t("installed")})`}
|
{t(team.name)} {isInstalled && `(${t("installed")})`}
|
||||||
</p>
|
</p>
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import type { ComponentProps } from "react";
|
import type { ComponentProps } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Shell from "@calcom/features/shell/Shell";
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { EmptyScreen } from "@calcom/ui";
|
import { EmptyScreen } from "@calcom/ui";
|
||||||
import { AlertCircle } from "@calcom/ui/components/icon";
|
import { AlertCircle } from "@calcom/ui/components/icon";
|
||||||
@@ -12,7 +12,7 @@ type AppsLayoutProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
actions?: (className?: string) => JSX.Element;
|
actions?: (className?: string) => JSX.Element;
|
||||||
emptyStore?: boolean;
|
emptyStore?: boolean;
|
||||||
} & Omit<ComponentProps<typeof Shell>, "actions">;
|
} & Omit<ComponentProps<typeof ShellMain>, "actions">;
|
||||||
|
|
||||||
export default function AppsLayout({ children, actions, emptyStore, ...rest }: AppsLayoutProps) {
|
export default function AppsLayout({ children, actions, emptyStore, ...rest }: AppsLayoutProps) {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
@@ -22,7 +22,7 @@ export default function AppsLayout({ children, actions, emptyStore, ...rest }: A
|
|||||||
|
|
||||||
if (session.status === "loading") return <></>;
|
if (session.status === "loading") return <></>;
|
||||||
return (
|
return (
|
||||||
<Shell {...rest} actions={actions?.("block")} hideHeadingOnMobile>
|
<ShellMain {...rest} actions={actions?.("block")} hideHeadingOnMobile>
|
||||||
<div className="flex flex-col xl:flex-row">
|
<div className="flex flex-col xl:flex-row">
|
||||||
<main className="w-full">
|
<main className="w-full">
|
||||||
{emptyStore ? (
|
{emptyStore ? (
|
||||||
@@ -38,7 +38,6 @@ export default function AppsLayout({ children, actions, emptyStore, ...rest }: A
|
|||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</Shell>
|
</ShellMain>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export const getLayout = (page: React.ReactElement) => <AppsLayout>{page}</AppsLayout>;
|
|
||||||
@@ -13,6 +13,7 @@ import type { DurationType } from "@calcom/lib/convertToNewDurationType";
|
|||||||
import convertToNewDurationType from "@calcom/lib/convertToNewDurationType";
|
import convertToNewDurationType from "@calcom/lib/convertToNewDurationType";
|
||||||
import findDurationType from "@calcom/lib/findDurationType";
|
import findDurationType from "@calcom/lib/findDurationType";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
|
import { ascendingLimitKeys, intervalLimitKeyToUnit } from "@calcom/lib/intervalLimit";
|
||||||
import type { PeriodType } from "@calcom/prisma/enums";
|
import type { PeriodType } from "@calcom/prisma/enums";
|
||||||
import type { IntervalLimit } from "@calcom/types/Calendar";
|
import type { IntervalLimit } from "@calcom/types/Calendar";
|
||||||
import { Button, DateRangePicker, InputField, Label, Select, SettingsToggle, TextField } from "@calcom/ui";
|
import { Button, DateRangePicker, InputField, Label, Select, SettingsToggle, TextField } from "@calcom/ui";
|
||||||
@@ -462,7 +463,6 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
|
|||||||
type="number"
|
type="number"
|
||||||
{...offsetStartLockedProps}
|
{...offsetStartLockedProps}
|
||||||
label={t("offset_start")}
|
label={t("offset_start")}
|
||||||
defaultValue={eventType.offsetStart}
|
|
||||||
{...formMethods.register("offsetStart")}
|
{...formMethods.register("offsetStart")}
|
||||||
addOnSuffix={<>{t("minutes")}</>}
|
addOnSuffix={<>{t("minutes")}</>}
|
||||||
hint={t("offset_start_description", {
|
hint={t("offset_start_description", {
|
||||||
@@ -477,11 +477,9 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
|
|||||||
|
|
||||||
type IntervalLimitsKey = keyof IntervalLimit;
|
type IntervalLimitsKey = keyof IntervalLimit;
|
||||||
|
|
||||||
const intervalOrderKeys = ["PER_DAY", "PER_WEEK", "PER_MONTH", "PER_YEAR"] as const;
|
const INTERVAL_LIMIT_OPTIONS = ascendingLimitKeys.map((key) => ({
|
||||||
|
|
||||||
const INTERVAL_LIMIT_OPTIONS = intervalOrderKeys.map((key) => ({
|
|
||||||
value: key as keyof IntervalLimit,
|
value: key as keyof IntervalLimit,
|
||||||
label: `Per ${key.split("_")[1].toLocaleLowerCase()}`,
|
label: `Per ${intervalLimitKeyToUnit(key)}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
type IntervalLimitItemProps = {
|
type IntervalLimitItemProps = {
|
||||||
@@ -590,8 +588,8 @@ const IntervalLimitsManager = <K extends "durationLimits" | "bookingLimits">({
|
|||||||
Object.entries(currentIntervalLimits)
|
Object.entries(currentIntervalLimits)
|
||||||
.sort(([limitKeyA], [limitKeyB]) => {
|
.sort(([limitKeyA], [limitKeyB]) => {
|
||||||
return (
|
return (
|
||||||
intervalOrderKeys.indexOf(limitKeyA as IntervalLimitsKey) -
|
ascendingLimitKeys.indexOf(limitKeyA as IntervalLimitsKey) -
|
||||||
intervalOrderKeys.indexOf(limitKeyB as IntervalLimitsKey)
|
ascendingLimitKeys.indexOf(limitKeyB as IntervalLimitsKey)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { z } from "zod";
|
|||||||
import type { EventLocationType } from "@calcom/app-store/locations";
|
import type { EventLocationType } from "@calcom/app-store/locations";
|
||||||
import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/app-store/locations";
|
import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/app-store/locations";
|
||||||
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
|
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
|
||||||
|
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
|
||||||
import cx from "@calcom/lib/classNames";
|
import cx from "@calcom/lib/classNames";
|
||||||
import { CAL_URL } from "@calcom/lib/constants";
|
import { CAL_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
@@ -116,6 +117,7 @@ export const EventSetupTab = (
|
|||||||
const [editingLocationType, setEditingLocationType] = useState<string>("");
|
const [editingLocationType, setEditingLocationType] = useState<string>("");
|
||||||
const [selectedLocation, setSelectedLocation] = useState<LocationOption | undefined>(undefined);
|
const [selectedLocation, setSelectedLocation] = useState<LocationOption | undefined>(undefined);
|
||||||
const [multipleDuration, setMultipleDuration] = useState(eventType.metadata?.multipleDuration);
|
const [multipleDuration, setMultipleDuration] = useState(eventType.metadata?.multipleDuration);
|
||||||
|
const orgBranding = useOrgBranding();
|
||||||
|
|
||||||
const locationOptions = props.locationOptions.map((locationOption) => {
|
const locationOptions = props.locationOptions.map((locationOption) => {
|
||||||
const options = locationOption.options.filter((option) => {
|
const options = locationOption.options.filter((option) => {
|
||||||
@@ -129,10 +131,12 @@ export const EventSetupTab = (
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const multipleDurationOptions = [5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 180].map((mins) => ({
|
const multipleDurationOptions = [5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 150, 180].map(
|
||||||
value: mins,
|
(mins) => ({
|
||||||
label: t("multiple_duration_mins", { count: mins }),
|
value: mins,
|
||||||
}));
|
label: t("multiple_duration_mins", { count: mins }),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const [selectedMultipleDuration, setSelectedMultipleDuration] = useState<
|
const [selectedMultipleDuration, setSelectedMultipleDuration] = useState<
|
||||||
MultiValue<{
|
MultiValue<{
|
||||||
@@ -383,6 +387,9 @@ export const EventSetupTab = (
|
|||||||
|
|
||||||
const lengthLockedProps = shouldLockDisableProps("length");
|
const lengthLockedProps = shouldLockDisableProps("length");
|
||||||
const descriptionLockedProps = shouldLockDisableProps("description");
|
const descriptionLockedProps = shouldLockDisableProps("description");
|
||||||
|
const urlPrefix = orgBranding
|
||||||
|
? orgBranding?.fullDomain.replace(/^(https?:|)\/\//, "")
|
||||||
|
: `${CAL_URL?.replace(/^(https?:|)\/\//, "")}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -411,10 +418,10 @@ export const EventSetupTab = (
|
|||||||
defaultValue={eventType.slug}
|
defaultValue={eventType.slug}
|
||||||
addOnLeading={
|
addOnLeading={
|
||||||
<>
|
<>
|
||||||
{CAL_URL?.replace(/^(https?:|)\/\//, "")}/
|
{urlPrefix}/
|
||||||
{!isManagedEventType
|
{!isManagedEventType
|
||||||
? team
|
? team
|
||||||
? "team/" + team.slug
|
? (orgBranding ? "" : "team/") + team.slug
|
||||||
: eventType.users[0].username
|
: eventType.users[0].username
|
||||||
: t("username_placeholder")}
|
: t("username_placeholder")}
|
||||||
/
|
/
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Trans } from "next-i18next";
|
||||||
|
import Link from "next/link";
|
||||||
import type { EventTypeSetupProps, FormValues } from "pages/event-types/[type]";
|
import type { EventTypeSetupProps, FormValues } from "pages/event-types/[type]";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import type { ComponentProps } from "react";
|
import type { ComponentProps } from "react";
|
||||||
@@ -99,6 +101,7 @@ const CheckedHostField = ({
|
|||||||
isFixed,
|
isFixed,
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
helperText,
|
||||||
...rest
|
...rest
|
||||||
}: {
|
}: {
|
||||||
labelText: string;
|
labelText: string;
|
||||||
@@ -107,6 +110,7 @@ const CheckedHostField = ({
|
|||||||
value: { isFixed: boolean; userId: number }[];
|
value: { isFixed: boolean; userId: number }[];
|
||||||
onChange?: (options: { isFixed: boolean; userId: number }[]) => void;
|
onChange?: (options: { isFixed: boolean; userId: number }[]) => void;
|
||||||
options?: Options<CheckedSelectOption>;
|
options?: Options<CheckedSelectOption>;
|
||||||
|
helperText?: React.ReactNode | string;
|
||||||
} & Omit<Partial<ComponentProps<typeof CheckedTeamSelect>>, "onChange" | "value">) => {
|
} & Omit<Partial<ComponentProps<typeof CheckedTeamSelect>>, "onChange" | "value">) => {
|
||||||
return (
|
return (
|
||||||
<div className="bg-muted flex flex-col space-y-5 p-4">
|
<div className="bg-muted flex flex-col space-y-5 p-4">
|
||||||
@@ -136,11 +140,24 @@ const CheckedHostField = ({
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
|
{helperText && <p className="text-subtle text-sm">{helperText}</p>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const FixedHostHelper = (
|
||||||
|
<Trans i18nKey="fixed_host_helper">
|
||||||
|
Add anyone who needs to attend the event.
|
||||||
|
<Link
|
||||||
|
className="underline underline-offset-2"
|
||||||
|
target="_blank"
|
||||||
|
href="https://cal.com/docs/enterprise-features/teams/round-robin-scheduling#fixed-hosts">
|
||||||
|
Learn more
|
||||||
|
</Link>
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
const RoundRobinHosts = ({
|
const RoundRobinHosts = ({
|
||||||
teamMembers,
|
teamMembers,
|
||||||
value,
|
value,
|
||||||
@@ -167,6 +184,7 @@ const RoundRobinHosts = ({
|
|||||||
value={value}
|
value={value}
|
||||||
placeholder={t("add_fixed_hosts")}
|
placeholder={t("add_fixed_hosts")}
|
||||||
labelText={t("fixed_hosts")}
|
labelText={t("fixed_hosts")}
|
||||||
|
helperText={FixedHostHelper}
|
||||||
/>
|
/>
|
||||||
<CheckedHostField
|
<CheckedHostField
|
||||||
options={teamMembers.sort(sortByLabel)}
|
options={teamMembers.sort(sortByLabel)}
|
||||||
@@ -175,6 +193,7 @@ const RoundRobinHosts = ({
|
|||||||
isFixed={false}
|
isFixed={false}
|
||||||
placeholder={t("add_attendees")}
|
placeholder={t("add_attendees")}
|
||||||
labelText={t("round_robin_hosts")}
|
labelText={t("round_robin_hosts")}
|
||||||
|
helperText={t("round_robin_helper")}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export const UsernameAvailabilityField = ({
|
|||||||
setInputUsernameValue={onChange}
|
setInputUsernameValue={onChange}
|
||||||
onSuccessMutation={onSuccessMutation}
|
onSuccessMutation={onSuccessMutation}
|
||||||
onErrorMutation={onErrorMutation}
|
onErrorMutation={onErrorMutation}
|
||||||
addOnLeading={usernamePrefix}
|
addOnLeading={`${usernamePrefix}/`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { useFlags } from "@calcom/features/flags/hooks";
|
|||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { MetaProvider } from "@calcom/ui";
|
import { MetaProvider } from "@calcom/ui";
|
||||||
|
|
||||||
import usePublicPage from "@lib/hooks/usePublicPage";
|
import useIsBookingPage from "@lib/hooks/useIsBookingPage";
|
||||||
import type { WithNonceProps } from "@lib/withNonce";
|
import type { WithNonceProps } from "@lib/withNonce";
|
||||||
|
|
||||||
import { useViewerI18n } from "@components/I18nLanguageHandler";
|
import { useViewerI18n } from "@components/I18nLanguageHandler";
|
||||||
@@ -247,7 +247,7 @@ function OrgBrandProvider({ children }: { children: React.ReactNode }) {
|
|||||||
|
|
||||||
const AppProviders = (props: AppPropsWithChildren) => {
|
const AppProviders = (props: AppPropsWithChildren) => {
|
||||||
// No need to have intercom on public pages - Good for Page Performance
|
// No need to have intercom on public pages - Good for Page Performance
|
||||||
const isPublicPage = usePublicPage();
|
const isBookingPage = useIsBookingPage();
|
||||||
const { pageProps, ...rest } = props;
|
const { pageProps, ...rest } = props;
|
||||||
const { _nonce, ...restPageProps } = pageProps;
|
const { _nonce, ...restPageProps } = pageProps;
|
||||||
const propsWithoutNonce = {
|
const propsWithoutNonce = {
|
||||||
@@ -267,7 +267,7 @@ const AppProviders = (props: AppPropsWithChildren) => {
|
|||||||
themeBasis={props.pageProps.themeBasis}
|
themeBasis={props.pageProps.themeBasis}
|
||||||
nonce={props.pageProps.nonce}
|
nonce={props.pageProps.nonce}
|
||||||
isThemeSupported={props.Component.isThemeSupported}
|
isThemeSupported={props.Component.isThemeSupported}
|
||||||
isBookingPage={props.Component.isBookingPage}
|
isBookingPage={props.Component.isBookingPage || isBookingPage}
|
||||||
router={props.router}>
|
router={props.router}>
|
||||||
<FeatureFlagsProvider>
|
<FeatureFlagsProvider>
|
||||||
<OrgBrandProvider>
|
<OrgBrandProvider>
|
||||||
@@ -281,7 +281,7 @@ const AppProviders = (props: AppPropsWithChildren) => {
|
|||||||
</EventCollectionProvider>
|
</EventCollectionProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isPublicPage) {
|
if (isBookingPage) {
|
||||||
return RemainingProviders;
|
return RemainingProviders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { usePathname, useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
|
export default function useIsBookingPage() {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const isBookingPage = ["/booking/", "/cancel", "/reschedule"].some((route) => pathname?.startsWith(route));
|
||||||
|
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const userParam = searchParams.get("user");
|
||||||
|
const teamParam = searchParams.get("team");
|
||||||
|
|
||||||
|
return !!(isBookingPage || userParam || teamParam);
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { usePathname } from "next/navigation";
|
|
||||||
|
|
||||||
export default function usePublicPage() {
|
|
||||||
const pathname = usePathname();
|
|
||||||
const isPublicPage = ["/[user]", "/booking", "/cancel", "/reschedule"].find((route) =>
|
|
||||||
pathname?.startsWith(route)
|
|
||||||
);
|
|
||||||
return isPublicPage;
|
|
||||||
}
|
|
||||||
@@ -25,8 +25,10 @@ if (!process.env.NEXTAUTH_URL && process.env.NEXT_PUBLIC_WEBAPP_URL) {
|
|||||||
if (!process.env.NEXT_PUBLIC_WEBSITE_URL) {
|
if (!process.env.NEXT_PUBLIC_WEBSITE_URL) {
|
||||||
process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL;
|
process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
if (process.env.CSP_POLICY === "strict" && process.env.NODE_ENV === "production") {
|
process.env.CSP_POLICY === "strict" &&
|
||||||
|
(process.env.CALCOM_ENV === "production" || process.env.NODE_ENV === "production")
|
||||||
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Strict CSP policy(for style-src) is not yet supported in production. You can experiment with it in Dev Mode"
|
"Strict CSP policy(for style-src) is not yet supported in production. You can experiment with it in Dev Mode"
|
||||||
);
|
);
|
||||||
@@ -127,7 +129,10 @@ const matcherConfigUserTypeEmbedRoute = {
|
|||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
/** @type {import("next").NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
i18n,
|
i18n: {
|
||||||
|
...i18n,
|
||||||
|
localeDetection: false,
|
||||||
|
},
|
||||||
productionBrowserSourceMaps: true,
|
productionBrowserSourceMaps: true,
|
||||||
/* We already do type check on GH actions */
|
/* We already do type check on GH actions */
|
||||||
typescript: {
|
typescript: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@calcom/web",
|
"name": "@calcom/web",
|
||||||
"version": "3.1.7",
|
"version": "3.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "ANALYZE=true next build",
|
"analyze": "ANALYZE=true next build",
|
||||||
@@ -166,6 +166,7 @@
|
|||||||
"msw": "^0.42.3",
|
"msw": "^0.42.3",
|
||||||
"postcss": "^8.4.18",
|
"postcss": "^8.4.18",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1",
|
||||||
|
"tailwindcss-animate": "^1.0.6",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.9.4"
|
"typescript": "^4.9.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants";
|
import { APP_NAME } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { Button, showToast } from "@calcom/ui";
|
import { Button, showToast } from "@calcom/ui";
|
||||||
import { Copy } from "@calcom/ui/components/icon";
|
import { Copy } from "@calcom/ui/components/icon";
|
||||||
@@ -21,14 +21,11 @@ export default function Error500() {
|
|||||||
<div className="rtl: bg-default m-auto rounded-md p-10 text-right ltr:text-left">
|
<div className="rtl: bg-default m-auto rounded-md p-10 text-right ltr:text-left">
|
||||||
<h1 className="font-cal text-emphasis text-6xl">500</h1>
|
<h1 className="font-cal text-emphasis text-6xl">500</h1>
|
||||||
<h2 className="text-emphasis mt-6 text-2xl font-medium">It's not you, it's us.</h2>
|
<h2 className="text-emphasis mt-6 text-2xl font-medium">It's not you, it's us.</h2>
|
||||||
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">
|
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">{t("something_went_wrong_on_our_end")}</p>
|
||||||
Something went wrong on our end. Get in touch with our support team, and we’ll get it fixed right
|
|
||||||
away for you.
|
|
||||||
</p>
|
|
||||||
{searchParams?.get("error") && (
|
{searchParams?.get("error") && (
|
||||||
<div className="mb-8 flex flex-col">
|
<div className="mb-8 flex flex-col">
|
||||||
<p className="text-default mb-4 max-w-2xl text-sm">
|
<p className="text-default mb-4 max-w-2xl text-sm">
|
||||||
Please provide the following text when contacting support to better help you:
|
{t("please_provide_following_text_to_suppport")}:
|
||||||
</p>
|
</p>
|
||||||
<pre className="bg-emphasis text-emphasis w-full max-w-2xl whitespace-normal break-words rounded-md p-4">
|
<pre className="bg-emphasis text-emphasis w-full max-w-2xl whitespace-normal break-words rounded-md p-4">
|
||||||
{searchParams?.get("error")}
|
{searchParams?.get("error")}
|
||||||
@@ -46,9 +43,9 @@ export default function Error500() {
|
|||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Button href={`${WEBSITE_URL}/support`}>{t("contact_support")}</Button>
|
<Button href="mailto:support@cal.com">{t("contact_support")}</Button>
|
||||||
<Button color="secondary" href="javascript:history.back()" className="ml-2">
|
<Button color="secondary" href="javascript:history.back()" className="ml-2">
|
||||||
Go back
|
{t("go_back")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { ssrInit } from "@server/lib/ssr";
|
|||||||
|
|
||||||
export function UserPage(props: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
export function UserPage(props: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
const { users, profile, eventTypes, markdownStrippedBio, entity } = props;
|
const { users, profile, eventTypes, markdownStrippedBio, entity } = props;
|
||||||
|
|
||||||
const [user] = users; //To be used when we only have a single user, not dynamic group
|
const [user] = users; //To be used when we only have a single user, not dynamic group
|
||||||
useTheme(profile.theme);
|
useTheme(profile.theme);
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
@@ -82,6 +83,10 @@ export function UserPage(props: InferGetServerSidePropsType<typeof getServerSide
|
|||||||
profile: { name: `${profile.name}`, image: null },
|
profile: { name: `${profile.name}`, image: null },
|
||||||
users: [{ username: `${user.username}`, name: `${user.name}` }],
|
users: [{ username: `${user.username}`, name: `${user.name}` }],
|
||||||
}}
|
}}
|
||||||
|
nextSeoProps={{
|
||||||
|
noindex: !profile.allowSEOIndexing,
|
||||||
|
nofollow: !profile.allowSEOIndexing,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={classNames(shouldAlignCentrally ? "mx-auto" : "", isEmbed ? "max-w-3xl" : "")}>
|
<div className={classNames(shouldAlignCentrally ? "mx-auto" : "", isEmbed ? "max-w-3xl" : "")}>
|
||||||
@@ -214,6 +219,7 @@ export type UserPageProps = {
|
|||||||
theme: string | null;
|
theme: string | null;
|
||||||
brandColor: string;
|
brandColor: string;
|
||||||
darkBrandColor: string;
|
darkBrandColor: string;
|
||||||
|
allowSEOIndexing: boolean;
|
||||||
};
|
};
|
||||||
users: Pick<User, "away" | "name" | "username" | "bio" | "verified">[];
|
users: Pick<User, "away" | "name" | "username" | "bio" | "verified">[];
|
||||||
themeBasis: string | null;
|
themeBasis: string | null;
|
||||||
@@ -276,6 +282,7 @@ export const getServerSideProps: GetServerSideProps<UserPageProps> = async (cont
|
|||||||
away: true,
|
away: true,
|
||||||
verified: true,
|
verified: true,
|
||||||
allowDynamicBooking: true,
|
allowDynamicBooking: true,
|
||||||
|
allowSEOIndexing: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -315,6 +322,7 @@ export const getServerSideProps: GetServerSideProps<UserPageProps> = async (cont
|
|||||||
theme: user.theme,
|
theme: user.theme,
|
||||||
brandColor: user.brandColor,
|
brandColor: user.brandColor,
|
||||||
darkBrandColor: user.darkBrandColor,
|
darkBrandColor: user.darkBrandColor,
|
||||||
|
allowSEOIndexing: user.allowSEOIndexing ?? true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const eventTypesWithHidden = await getEventTypesWithHiddenFromDB(user.id);
|
const eventTypesWithHidden = await getEventTypesWithHiddenFromDB(user.id);
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import { z } from "zod";
|
|||||||
import { Booker } from "@calcom/atoms";
|
import { Booker } from "@calcom/atoms";
|
||||||
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
||||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||||
import { getBookingForReschedule, getBookingForSeatedEvent } from "@calcom/features/bookings/lib/get-booking";
|
import {
|
||||||
|
getBookingForReschedule,
|
||||||
|
getBookingForSeatedEvent,
|
||||||
|
getMultipleDurationValue,
|
||||||
|
} from "@calcom/features/bookings/lib/get-booking";
|
||||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
|
import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
@@ -26,8 +30,10 @@ export default function Type({
|
|||||||
booking,
|
booking,
|
||||||
away,
|
away,
|
||||||
isBrandingHidden,
|
isBrandingHidden,
|
||||||
|
isSEOIndexable,
|
||||||
rescheduleUid,
|
rescheduleUid,
|
||||||
entity,
|
entity,
|
||||||
|
duration,
|
||||||
}: PageProps) {
|
}: PageProps) {
|
||||||
return (
|
return (
|
||||||
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
||||||
@@ -36,6 +42,7 @@ export default function Type({
|
|||||||
eventSlug={slug}
|
eventSlug={slug}
|
||||||
rescheduleUid={rescheduleUid ?? undefined}
|
rescheduleUid={rescheduleUid ?? undefined}
|
||||||
hideBranding={isBrandingHidden}
|
hideBranding={isBrandingHidden}
|
||||||
|
isSEOIndexable={isSEOIndexable ?? true}
|
||||||
entity={entity}
|
entity={entity}
|
||||||
/>
|
/>
|
||||||
<Booker
|
<Booker
|
||||||
@@ -45,6 +52,7 @@ export default function Type({
|
|||||||
isAway={away}
|
isAway={away}
|
||||||
hideBranding={isBrandingHidden}
|
hideBranding={isBrandingHidden}
|
||||||
entity={entity}
|
entity={entity}
|
||||||
|
duration={duration}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
@@ -55,7 +63,7 @@ Type.PageWrapper = PageWrapper;
|
|||||||
|
|
||||||
async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
||||||
const { user: usernames, type: slug } = paramsSchema.parse(context.params);
|
const { user: usernames, type: slug } = paramsSchema.parse(context.params);
|
||||||
const { rescheduleUid, bookingUid } = context.query;
|
const { rescheduleUid, bookingUid, duration: queryDuration } = context.query;
|
||||||
|
|
||||||
const { ssrInit } = await import("@server/lib/ssr");
|
const { ssrInit } = await import("@server/lib/ssr");
|
||||||
const ssr = await ssrInit(context);
|
const ssr = await ssrInit(context);
|
||||||
@@ -111,12 +119,18 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
entity: eventData.entity,
|
entity: eventData.entity,
|
||||||
|
duration: getMultipleDurationValue(
|
||||||
|
eventData.metadata?.multipleDuration,
|
||||||
|
queryDuration,
|
||||||
|
eventData.length
|
||||||
|
),
|
||||||
booking,
|
booking,
|
||||||
user: usernames.join("+"),
|
user: usernames.join("+"),
|
||||||
slug,
|
slug,
|
||||||
away: false,
|
away: false,
|
||||||
trpcState: ssr.dehydrate(),
|
trpcState: ssr.dehydrate(),
|
||||||
isBrandingHidden: false,
|
isBrandingHidden: false,
|
||||||
|
isSEOIndexable: true,
|
||||||
themeBasis: null,
|
themeBasis: null,
|
||||||
bookingUid: bookingUid ? `${bookingUid}` : null,
|
bookingUid: bookingUid ? `${bookingUid}` : null,
|
||||||
rescheduleUid: rescheduleUid ? `${rescheduleUid}` : null,
|
rescheduleUid: rescheduleUid ? `${rescheduleUid}` : null,
|
||||||
@@ -127,7 +141,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
|||||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||||
const { user: usernames, type: slug } = paramsSchema.parse(context.params);
|
const { user: usernames, type: slug } = paramsSchema.parse(context.params);
|
||||||
const username = usernames[0];
|
const username = usernames[0];
|
||||||
const { rescheduleUid, bookingUid } = context.query;
|
const { rescheduleUid, bookingUid, duration: queryDuration } = context.query;
|
||||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(
|
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(
|
||||||
context.req.headers.host ?? "",
|
context.req.headers.host ?? "",
|
||||||
context.params?.orgSlug
|
context.params?.orgSlug
|
||||||
@@ -143,6 +157,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
|
|||||||
select: {
|
select: {
|
||||||
away: true,
|
away: true,
|
||||||
hideBranding: true,
|
hideBranding: true,
|
||||||
|
allowSEOIndexing: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -177,12 +192,18 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
booking,
|
booking,
|
||||||
|
duration: getMultipleDurationValue(
|
||||||
|
eventData.metadata?.multipleDuration,
|
||||||
|
queryDuration,
|
||||||
|
eventData.length
|
||||||
|
),
|
||||||
away: user?.away,
|
away: user?.away,
|
||||||
user: username,
|
user: username,
|
||||||
slug,
|
slug,
|
||||||
entity: eventData.entity,
|
entity: eventData.entity,
|
||||||
trpcState: ssr.dehydrate(),
|
trpcState: ssr.dehydrate(),
|
||||||
isBrandingHidden: user?.hideBranding,
|
isBrandingHidden: user?.hideBranding,
|
||||||
|
isSEOIndexable: user?.allowSEOIndexing,
|
||||||
themeBasis: username,
|
themeBasis: username,
|
||||||
bookingUid: bookingUid ? `${bookingUid}` : null,
|
bookingUid: bookingUid ? `${bookingUid}` : null,
|
||||||
rescheduleUid: rescheduleUid ? `${rescheduleUid}` : null,
|
rescheduleUid: rescheduleUid ? `${rescheduleUid}` : null,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
|
||||||
import type { AppProps } from "@lib/app-providers";
|
import type { AppProps } from "@lib/app-providers";
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import type { DocumentContext, DocumentProps } from "next/document";
|
|||||||
import Document, { Head, Html, Main, NextScript } from "next/document";
|
import Document, { Head, Html, Main, NextScript } from "next/document";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||||
|
|
||||||
import { csp } from "@lib/csp";
|
import { csp } from "@lib/csp";
|
||||||
|
|
||||||
type Props = Record<string, unknown> & DocumentProps;
|
type Props = Record<string, unknown> & DocumentProps;
|
||||||
@@ -49,7 +51,7 @@ class MyDocument extends Document<Props> {
|
|||||||
<meta name="msapplication-TileColor" content="#ff0000" />
|
<meta name="msapplication-TileColor" content="#ff0000" />
|
||||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f9fafb" />
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f9fafb" />
|
||||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1C1C1C" />
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1C1C1C" />
|
||||||
{(process.env.NODE_ENV === "development" || process.env.VERCEL_ENV === "preview") && (
|
{(!IS_PRODUCTION || process.env.VERCEL_ENV === "preview") && (
|
||||||
// eslint-disable-next-line @next/next/no-sync-scripts
|
// eslint-disable-next-line @next/next/no-sync-scripts
|
||||||
<script
|
<script
|
||||||
data-project-id="KjpMrKTnXquJVKfeqmjdTffVPf1a6Unw2LZ58iE4"
|
data-project-id="KjpMrKTnXquJVKfeqmjdTffVPf1a6Unw2LZ58iE4"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { authenticator } from "otplib";
|
|
||||||
|
|
||||||
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
|
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
|
||||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||||
import { verifyPassword } from "@calcom/features/auth/lib/verifyPassword";
|
import { verifyPassword } from "@calcom/features/auth/lib/verifyPassword";
|
||||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||||
|
import { totpAuthenticatorCheck } from "@calcom/lib/totp";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { IdentityProvider } from "@calcom/prisma/client";
|
import { IdentityProvider } from "@calcom/prisma/client";
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If user has 2fa enabled, check if body.code is correct
|
// If user has 2fa enabled, check if body.code is correct
|
||||||
const isValidToken = authenticator.check(req.body.code, secret);
|
const isValidToken = totpAuthenticatorCheck(req.body.code, secret);
|
||||||
if (!isValidToken) {
|
if (!isValidToken) {
|
||||||
return res.status(400).json({ error: ErrorCode.IncorrectTwoFactorCode });
|
return res.status(400).json({ error: ErrorCode.IncorrectTwoFactorCode });
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { authenticator } from "otplib";
|
|
||||||
|
|
||||||
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
|
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
|
||||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||||
|
import { totpAuthenticatorCheck } from "@calcom/lib/totp";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@@ -48,7 +48,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
return res.status(500).json({ error: ErrorCode.InternalServerError });
|
return res.status(500).json({ error: ErrorCode.InternalServerError });
|
||||||
}
|
}
|
||||||
|
|
||||||
const isValidToken = authenticator.check(req.body.code, secret);
|
const isValidToken = totpAuthenticatorCheck(req.body.code, secret);
|
||||||
if (!isValidToken) {
|
if (!isValidToken) {
|
||||||
return res.status(400).json({ error: ErrorCode.IncorrectTwoFactorCode });
|
return res.status(400).json({ error: ErrorCode.IncorrectTwoFactorCode });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { renderEmail } from "@calcom/emails";
|
import { renderEmail } from "@calcom/emails";
|
||||||
|
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
if (process.env.NODE_ENV !== "development") return res.write("Only for development purposes"), res.end();
|
if (IS_PRODUCTION) return res.write("Only for development purposes"), res.end();
|
||||||
const t = await getTranslation("en", "common");
|
const t = await getTranslation("en", "common");
|
||||||
const language = { translate: t, locale: "en" };
|
const language = { translate: t, locale: "en" };
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default, config } from "@calcom/features/ee/payments/api/paypal-webhook";
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
|
||||||
|
import { kycVerificationRouter } from "@calcom/trpc/server/routers/viewer/kycVerification/_router";
|
||||||
|
|
||||||
|
export default createNextApiHandler(kycVerificationRouter);
|
||||||
@@ -9,6 +9,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { getAppWithMetadata } from "@calcom/app-store/_appRegistry";
|
import { getAppWithMetadata } from "@calcom/app-store/_appRegistry";
|
||||||
import { getAppAssetFullPath } from "@calcom/app-store/getAppAssetFullPath";
|
import { getAppAssetFullPath } from "@calcom/app-store/getAppAssetFullPath";
|
||||||
|
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
|
|
||||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
@@ -38,7 +39,7 @@ const sourceSchema = z.object({
|
|||||||
function SingleAppPage(props: inferSSRProps<typeof getStaticProps>) {
|
function SingleAppPage(props: inferSSRProps<typeof getStaticProps>) {
|
||||||
// If it's not production environment, it would be a better idea to inform that the App is disabled.
|
// If it's not production environment, it would be a better idea to inform that the App is disabled.
|
||||||
if (props.isAppDisabled) {
|
if (props.isAppDisabled) {
|
||||||
if (process.env.NODE_ENV !== "production") {
|
if (!IS_PRODUCTION) {
|
||||||
// TODO: Improve disabled App UI. This is just a placeholder.
|
// TODO: Improve disabled App UI. This is just a placeholder.
|
||||||
return (
|
return (
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
@@ -123,7 +124,7 @@ export const getStaticProps = async (ctx: GetStaticPropsContext) => {
|
|||||||
const isAppAvailableInFileSystem = appMeta;
|
const isAppAvailableInFileSystem = appMeta;
|
||||||
const isAppDisabled = isAppAvailableInFileSystem && (!appFromDb || !appFromDb.enabled);
|
const isAppDisabled = isAppAvailableInFileSystem && (!appFromDb || !appFromDb.enabled);
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production" && isAppDisabled) {
|
if (!IS_PRODUCTION && isAppDisabled) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
isAppDisabled: true as const,
|
isAppDisabled: true as const,
|
||||||
|
|||||||
@@ -40,9 +40,11 @@ export default function Apps({ apps }: InferGetStaticPropsType<typeof getStaticP
|
|||||||
}>
|
}>
|
||||||
<div className="mb-16">
|
<div className="mb-16">
|
||||||
<div className="grid-col-1 grid grid-cols-1 gap-3 md:grid-cols-3">
|
<div className="grid-col-1 grid grid-cols-1 gap-3 md:grid-cols-3">
|
||||||
{apps.map((app) => {
|
{apps
|
||||||
return <AppCard key={app.slug} app={app} />;
|
.sort((a, b) => (b.installCount || 0) - (a.installCount || 0))
|
||||||
})}
|
.map((app) => {
|
||||||
|
return <AppCard key={app.slug} app={app} />;
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Shell>
|
</Shell>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { ChangeEventHandler } from "react";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { getAppRegistry, getAppRegistryWithCredentials } from "@calcom/app-store/_appRegistry";
|
import { getAppRegistry, getAppRegistryWithCredentials } from "@calcom/app-store/_appRegistry";
|
||||||
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||||
import getUserAdminTeams from "@calcom/features/ee/teams/lib/getUserAdminTeams";
|
import getUserAdminTeams from "@calcom/features/ee/teams/lib/getUserAdminTeams";
|
||||||
import type { UserAdminTeams } from "@calcom/features/ee/teams/lib/getUserAdminTeams";
|
import type { UserAdminTeams } from "@calcom/features/ee/teams/lib/getUserAdminTeams";
|
||||||
@@ -94,6 +95,7 @@ export default function Apps({
|
|||||||
}
|
}
|
||||||
|
|
||||||
Apps.PageWrapper = PageWrapper;
|
Apps.PageWrapper = PageWrapper;
|
||||||
|
Apps.getLayout = getLayout;
|
||||||
|
|
||||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||||
const { req, res } = context;
|
const { req, res } = context;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => {
|
|||||||
<DateOverrideInputDialog
|
<DateOverrideInputDialog
|
||||||
workingHours={workingHours}
|
workingHours={workingHours}
|
||||||
excludedDates={excludedDates}
|
excludedDates={excludedDates}
|
||||||
onChange={(ranges) => append({ ranges })}
|
onChange={(ranges) => ranges.forEach((range) => append({ ranges: [range] }))}
|
||||||
Trigger={
|
Trigger={
|
||||||
<Button color="secondary" StartIcon={Plus} data-testid="add-override">
|
<Button color="secondary" StartIcon={Plus} data-testid="add-override">
|
||||||
{t("add_an_override")}
|
{t("add_an_override")}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules";
|
import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules";
|
||||||
import Shell from "@calcom/features/shell/Shell";
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { HttpError } from "@calcom/lib/http-error";
|
import { HttpError } from "@calcom/lib/http-error";
|
||||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||||
@@ -130,15 +131,17 @@ export default function AvailabilityPage() {
|
|||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Shell
|
<ShellMain
|
||||||
heading={t("availability")}
|
heading={t("availability")}
|
||||||
hideHeadingOnMobile
|
hideHeadingOnMobile
|
||||||
subtitle={t("configure_availability")}
|
subtitle={t("configure_availability")}
|
||||||
CTA={<NewScheduleButton />}>
|
CTA={<NewScheduleButton />}>
|
||||||
<WithQuery success={({ data }) => <AvailabilityList {...data} />} customLoader={<SkeletonLoader />} />
|
<WithQuery success={({ data }) => <AvailabilityList {...data} />} customLoader={<SkeletonLoader />} />
|
||||||
</Shell>
|
</ShellMain>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AvailabilityPage.getLayout = getLayout;
|
||||||
|
|
||||||
AvailabilityPage.PageWrapper = PageWrapper;
|
AvailabilityPage.PageWrapper = PageWrapper;
|
||||||
@@ -23,12 +23,9 @@ import {
|
|||||||
useIsEmbed,
|
useIsEmbed,
|
||||||
} from "@calcom/embed-core/embed-iframe";
|
} from "@calcom/embed-core/embed-iframe";
|
||||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||||
import { SystemField } from "@calcom/features/bookings/lib/SystemField";
|
import { SMS_REMINDER_NUMBER_FIELD, SystemField } from "@calcom/features/bookings/lib/SystemField";
|
||||||
import { getBookingWithResponses } from "@calcom/features/bookings/lib/get-booking";
|
import { getBookingWithResponses } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import {
|
import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields";
|
||||||
getBookingFieldsWithSystemFields,
|
|
||||||
SMS_REMINDER_NUMBER_FIELD,
|
|
||||||
} from "@calcom/features/bookings/lib/getBookingFields";
|
|
||||||
import { parseRecurringEvent } from "@calcom/lib";
|
import { parseRecurringEvent } from "@calcom/lib";
|
||||||
import { APP_NAME } from "@calcom/lib/constants";
|
import { APP_NAME } from "@calcom/lib/constants";
|
||||||
import {
|
import {
|
||||||
@@ -96,7 +93,7 @@ const querySchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default function Success(props: SuccessProps) {
|
export default function Success(props: SuccessProps) {
|
||||||
const { t } = useLocale();
|
const { t, i18n } = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const routerQuery = useRouterQuery();
|
const routerQuery = useRouterQuery();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
@@ -113,7 +110,8 @@ export default function Success(props: SuccessProps) {
|
|||||||
const attendeeTimeZone = props?.bookingInfo?.attendees.find(
|
const attendeeTimeZone = props?.bookingInfo?.attendees.find(
|
||||||
(attendee) => attendee.email === email
|
(attendee) => attendee.email === email
|
||||||
)?.timeZone;
|
)?.timeZone;
|
||||||
const tz = isSuccessBookingPage && attendeeTimeZone ? attendeeTimeZone : props.tz ? props.tz : timeZone();
|
|
||||||
|
const tz = props.tz ? props.tz : isSuccessBookingPage && attendeeTimeZone ? attendeeTimeZone : timeZone();
|
||||||
|
|
||||||
const location = props.bookingInfo.location as ReturnType<typeof getEventLocationValue>;
|
const location = props.bookingInfo.location as ReturnType<typeof getEventLocationValue>;
|
||||||
|
|
||||||
@@ -314,7 +312,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
<Link
|
<Link
|
||||||
href={allRemainingBookings ? "/bookings/recurring" : "/bookings/upcoming"}
|
href={allRemainingBookings ? "/bookings/recurring" : "/bookings/upcoming"}
|
||||||
className="hover:bg-subtle text-subtle hover:text-default mt-2 inline-flex px-1 py-2 text-sm dark:hover:bg-transparent">
|
className="hover:bg-subtle text-subtle hover:text-default mt-2 inline-flex px-1 py-2 text-sm dark:hover:bg-transparent">
|
||||||
<ChevronLeft className="h-5 w-5" /> {t("back_to_bookings")}
|
<ChevronLeft className="h-5 w-5 rtl:rotate-180" /> {t("back_to_bookings")}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -394,7 +392,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
</h4>
|
</h4>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="border-subtle text-default mt-8 grid grid-cols-3 border-t pt-8 text-left">
|
<div className="border-subtle text-default mt-8 grid grid-cols-3 border-t pt-8 text-left rtl:text-right">
|
||||||
{(isCancelled || reschedule) && cancellationReason && (
|
{(isCancelled || reschedule) && cancellationReason && (
|
||||||
<>
|
<>
|
||||||
<div className="font-medium">
|
<div className="font-medium">
|
||||||
@@ -480,6 +478,21 @@ export default function Success(props: SuccessProps) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{props.paymentStatus && (
|
||||||
|
<>
|
||||||
|
<div className="mt-3 font-medium">
|
||||||
|
{props.paymentStatus.paymentOption === "HOLD"
|
||||||
|
? t("complete_your_booking")
|
||||||
|
: t("payment")}
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 mb-2 mt-3">
|
||||||
|
{new Intl.NumberFormat(i18n.language, {
|
||||||
|
style: "currency",
|
||||||
|
currency: props.paymentStatus.currency,
|
||||||
|
}).format(props.paymentStatus.amount / 100.0)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{bookingInfo?.description && (
|
{bookingInfo?.description && (
|
||||||
<>
|
<>
|
||||||
<div className="mt-9 font-medium">{t("additional_notes")}</div>
|
<div className="mt-9 font-medium">{t("additional_notes")}</div>
|
||||||
@@ -715,7 +728,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
</div>
|
</div>
|
||||||
{isGmail && (
|
{isGmail && (
|
||||||
<Alert
|
<Alert
|
||||||
className="main -mb-20 mt-4 inline-block text-left sm:-mt-4 sm:mb-4 sm:w-full sm:max-w-xl sm:align-middle"
|
className="main -mb-20 mt-4 inline-block ltr:text-right rtl:text-right sm:-mt-4 sm:mb-4 sm:w-full sm:max-w-xl sm:align-middle"
|
||||||
severity="warning"
|
severity="warning"
|
||||||
message={
|
message={
|
||||||
<div>
|
<div>
|
||||||
@@ -1117,6 +1130,9 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
select: {
|
select: {
|
||||||
success: true,
|
success: true,
|
||||||
refunded: true,
|
refunded: true,
|
||||||
|
currency: true,
|
||||||
|
amount: true,
|
||||||
|
paymentOption: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||||
import type { GetStaticPaths, GetStaticProps } from "next";
|
import type { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
|
import React from "react";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
|
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
|
||||||
import BookingLayout from "@calcom/features/bookings/layout/BookingLayout";
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
|
import { FiltersContainer } from "@calcom/features/bookings/components/FiltersContainer";
|
||||||
import type { filterQuerySchema } from "@calcom/features/bookings/lib/useFilterQuery";
|
import type { filterQuerySchema } from "@calcom/features/bookings/lib/useFilterQuery";
|
||||||
import { useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
|
import { useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
|
||||||
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback";
|
import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback";
|
||||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
import { HorizontalTabs } from "@calcom/ui";
|
||||||
|
import type { VerticalTabItemProps, HorizontalTabItemProps } from "@calcom/ui";
|
||||||
import { Alert, Button, EmptyScreen } from "@calcom/ui";
|
import { Alert, Button, EmptyScreen } from "@calcom/ui";
|
||||||
import { Calendar } from "@calcom/ui/components/icon";
|
import { Calendar } from "@calcom/ui/components/icon";
|
||||||
|
|
||||||
@@ -32,6 +37,28 @@ type RecurringInfo = {
|
|||||||
bookings: { [key: string]: Date[] };
|
bookings: { [key: string]: Date[] };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tabs: (VerticalTabItemProps | HorizontalTabItemProps)[] = [
|
||||||
|
{
|
||||||
|
name: "upcoming",
|
||||||
|
href: "/bookings/upcoming",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unconfirmed",
|
||||||
|
href: "/bookings/unconfirmed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recurring",
|
||||||
|
href: "/bookings/recurring",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "past",
|
||||||
|
href: "/bookings/past",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cancelled",
|
||||||
|
href: "/bookings/cancelled",
|
||||||
|
},
|
||||||
|
];
|
||||||
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
|
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
|
||||||
|
|
||||||
const descriptionByStatus: Record<NonNullable<BookingListingStatus>, string> = {
|
const descriptionByStatus: Record<NonNullable<BookingListingStatus>, string> = {
|
||||||
@@ -112,90 +139,101 @@ export default function Bookings() {
|
|||||||
const [animationParentRef] = useAutoAnimate<HTMLDivElement>();
|
const [animationParentRef] = useAutoAnimate<HTMLDivElement>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BookingLayout heading={t("bookings")} subtitle={t("bookings_description")}>
|
<ShellMain hideHeadingOnMobile heading={t("bookings")} subtitle={t("bookings_description")}>
|
||||||
<div className="flex w-full flex-col" ref={animationParentRef}>
|
<div className="flex flex-col">
|
||||||
{query.status === "error" && (
|
<div className="flex flex-col flex-wrap lg:flex-row">
|
||||||
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
<HorizontalTabs tabs={tabs} />
|
||||||
)}
|
<div className="max-w-full overflow-x-auto xl:ml-auto">
|
||||||
{(query.status === "loading" || query.isPaused) && <SkeletonLoader />}
|
<FiltersContainer />
|
||||||
{query.status === "success" && !isEmpty && (
|
</div>
|
||||||
<>
|
</div>
|
||||||
{!!bookingsToday.length && status === "upcoming" && (
|
<main className="w-full">
|
||||||
<div className="mb-6 pt-2 xl:pt-0">
|
<div className="flex w-full flex-col" ref={animationParentRef}>
|
||||||
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
{query.status === "error" && (
|
||||||
<p className="text-subtle mb-2 text-xs font-medium uppercase leading-4">{t("today")}</p>
|
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
||||||
<div className="border-subtle overflow-hidden rounded-md border">
|
)}
|
||||||
<table className="w-full max-w-full table-fixed">
|
{(query.status === "loading" || query.isPaused) && <SkeletonLoader />}
|
||||||
<tbody className="bg-default divide-subtle divide-y" data-testid="today-bookings">
|
{query.status === "success" && !isEmpty && (
|
||||||
<Fragment>
|
<>
|
||||||
{bookingsToday.map((booking: BookingOutput) => (
|
{!!bookingsToday.length && status === "upcoming" && (
|
||||||
<BookingListItem
|
<div className="mb-6 pt-2 xl:pt-0">
|
||||||
key={booking.id}
|
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
||||||
listingStatus={status}
|
<p className="text-subtle mb-2 text-xs font-medium uppercase leading-4">{t("today")}</p>
|
||||||
recurringInfo={recurringInfoToday}
|
<div className="border-subtle overflow-hidden rounded-md border">
|
||||||
{...booking}
|
<table className="w-full max-w-full table-fixed">
|
||||||
/>
|
<tbody className="bg-default divide-subtle divide-y" data-testid="today-bookings">
|
||||||
|
<Fragment>
|
||||||
|
{bookingsToday.map((booking: BookingOutput) => (
|
||||||
|
<BookingListItem
|
||||||
|
key={booking.id}
|
||||||
|
listingStatus={status}
|
||||||
|
recurringInfo={recurringInfoToday}
|
||||||
|
{...booking}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Fragment>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="pt-2 xl:pt-0">
|
||||||
|
<div className="border-subtle overflow-hidden rounded-md border">
|
||||||
|
<table className="w-full max-w-full table-fixed">
|
||||||
|
<tbody className="bg-default divide-subtle divide-y" data-testid="bookings">
|
||||||
|
{query.data.pages.map((page, index) => (
|
||||||
|
<Fragment key={index}>
|
||||||
|
{page.bookings.filter(filterBookings).map((booking: BookingOutput) => {
|
||||||
|
const recurringInfo = page.recurringInfo.find(
|
||||||
|
(info) => info.recurringEventId === booking.recurringEventId
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<BookingListItem
|
||||||
|
key={booking.id}
|
||||||
|
listingStatus={status}
|
||||||
|
recurringInfo={recurringInfo}
|
||||||
|
{...booking}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</Fragment>
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
|
<div className="text-default p-4 text-center" ref={buttonInView.ref}>
|
||||||
|
<Button
|
||||||
|
color="minimal"
|
||||||
|
loading={query.isFetchingNextPage}
|
||||||
|
disabled={!query.hasNextPage}
|
||||||
|
onClick={() => query.fetchNextPage()}>
|
||||||
|
{query.hasNextPage ? t("load_more_results") : t("no_more_results")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{query.status === "success" && isEmpty && (
|
||||||
|
<div className="flex items-center justify-center pt-2 xl:pt-0">
|
||||||
|
<EmptyScreen
|
||||||
|
Icon={Calendar}
|
||||||
|
headline={t("no_status_bookings_yet", { status: t(status).toLowerCase() })}
|
||||||
|
description={t("no_status_bookings_yet_description", {
|
||||||
|
status: t(status).toLowerCase(),
|
||||||
|
description: t(descriptionByStatus[status]),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="pt-2 xl:pt-0">
|
|
||||||
<div className="border-subtle overflow-hidden rounded-md border">
|
|
||||||
<table className="w-full max-w-full table-fixed">
|
|
||||||
<tbody className="bg-default divide-subtle divide-y" data-testid="bookings">
|
|
||||||
{query.data.pages.map((page, index) => (
|
|
||||||
<Fragment key={index}>
|
|
||||||
{page.bookings.filter(filterBookings).map((booking: BookingOutput) => {
|
|
||||||
const recurringInfo = page.recurringInfo.find(
|
|
||||||
(info) => info.recurringEventId === booking.recurringEventId
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<BookingListItem
|
|
||||||
key={booking.id}
|
|
||||||
listingStatus={status}
|
|
||||||
recurringInfo={recurringInfo}
|
|
||||||
{...booking}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div className="text-default p-4 text-center" ref={buttonInView.ref}>
|
|
||||||
<Button
|
|
||||||
color="minimal"
|
|
||||||
loading={query.isFetchingNextPage}
|
|
||||||
disabled={!query.hasNextPage}
|
|
||||||
onClick={() => query.fetchNextPage()}>
|
|
||||||
{query.hasNextPage ? t("load_more_results") : t("no_more_results")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{query.status === "success" && isEmpty && (
|
|
||||||
<div className="flex items-center justify-center pt-2 xl:pt-0">
|
|
||||||
<EmptyScreen
|
|
||||||
Icon={Calendar}
|
|
||||||
headline={t("no_status_bookings_yet", { status: t(status).toLowerCase() })}
|
|
||||||
description={t("no_status_bookings_yet_description", {
|
|
||||||
status: t(status).toLowerCase(),
|
|
||||||
description: t(descriptionByStatus[status]),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</BookingLayout>
|
</ShellMain>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bookings.PageWrapper = PageWrapper;
|
Bookings.PageWrapper = PageWrapper;
|
||||||
|
Bookings.getLayout = getLayout;
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||||
const params = querySchema.safeParse(ctx.params);
|
const params = querySchema.safeParse(ctx.params);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|||||||
import { Booker } from "@calcom/atoms";
|
import { Booker } from "@calcom/atoms";
|
||||||
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
||||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||||
import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booking";
|
import { getBookingForReschedule, getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
import slugify from "@calcom/lib/slugify";
|
import slugify from "@calcom/lib/slugify";
|
||||||
@@ -26,6 +26,7 @@ export default function Type({
|
|||||||
isBrandingHidden,
|
isBrandingHidden,
|
||||||
isTeamEvent,
|
isTeamEvent,
|
||||||
entity,
|
entity,
|
||||||
|
duration,
|
||||||
}: PageProps) {
|
}: PageProps) {
|
||||||
return (
|
return (
|
||||||
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
||||||
@@ -44,6 +45,7 @@ export default function Type({
|
|||||||
hideBranding={isBrandingHidden}
|
hideBranding={isBrandingHidden}
|
||||||
isTeamEvent={isTeamEvent}
|
isTeamEvent={isTeamEvent}
|
||||||
entity={entity}
|
entity={entity}
|
||||||
|
duration={duration}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
@@ -54,7 +56,7 @@ Type.isBookingPage = true;
|
|||||||
|
|
||||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||||
const { link, slug } = paramsSchema.parse(context.params);
|
const { link, slug } = paramsSchema.parse(context.params);
|
||||||
const { rescheduleUid } = context.query;
|
const { rescheduleUid, duration: queryDuration } = context.query;
|
||||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||||
const org = isValidOrgDomain ? currentOrgDomain : null;
|
const org = isValidOrgDomain ? currentOrgDomain : null;
|
||||||
|
|
||||||
@@ -133,6 +135,11 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
entity: eventData.entity,
|
entity: eventData.entity,
|
||||||
|
duration: getMultipleDurationValue(
|
||||||
|
eventData.metadata?.multipleDuration,
|
||||||
|
queryDuration,
|
||||||
|
eventData.length
|
||||||
|
),
|
||||||
booking,
|
booking,
|
||||||
away: user?.away,
|
away: user?.away,
|
||||||
user: username,
|
user: username,
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ const EventTypePage = (props: EventTypeSetupProps) => {
|
|||||||
startDate: periodDates.startDate,
|
startDate: periodDates.startDate,
|
||||||
endDate: periodDates.endDate,
|
endDate: periodDates.endDate,
|
||||||
},
|
},
|
||||||
|
offsetStart: eventType.offsetStart,
|
||||||
bookingFields: eventType.bookingFields,
|
bookingFields: eventType.bookingFields,
|
||||||
periodType: eventType.periodType,
|
periodType: eventType.periodType,
|
||||||
periodCountCalendarDays: eventType.periodCountCalendarDays ? "1" : "0",
|
periodCountCalendarDays: eventType.periodCountCalendarDays ? "1" : "0",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { FC } from "react";
|
|||||||
import { memo, useEffect, useState } from "react";
|
import { memo, useEffect, useState } from "react";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
|
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
|
||||||
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
|
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
|
||||||
import { EventTypeEmbedButton, EventTypeEmbedDialog } from "@calcom/features/embed/EventTypeEmbed";
|
import { EventTypeEmbedButton, EventTypeEmbedDialog } from "@calcom/features/embed/EventTypeEmbed";
|
||||||
@@ -15,7 +16,7 @@ import CreateEventTypeDialog from "@calcom/features/eventtypes/components/Create
|
|||||||
import { DuplicateDialog } from "@calcom/features/eventtypes/components/DuplicateDialog";
|
import { DuplicateDialog } from "@calcom/features/eventtypes/components/DuplicateDialog";
|
||||||
import { TeamsFilter } from "@calcom/features/filters/components/TeamsFilter";
|
import { TeamsFilter } from "@calcom/features/filters/components/TeamsFilter";
|
||||||
import { getTeamsFiltersFromQuery } from "@calcom/features/filters/lib/getTeamsFiltersFromQuery";
|
import { getTeamsFiltersFromQuery } from "@calcom/features/filters/lib/getTeamsFiltersFromQuery";
|
||||||
import Shell from "@calcom/features/shell/Shell";
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { APP_NAME, CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
import { APP_NAME, CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl";
|
import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
@@ -715,10 +716,7 @@ const EventTypeListHeading = ({
|
|||||||
<Avatar
|
<Avatar
|
||||||
alt={profile?.name || ""}
|
alt={profile?.name || ""}
|
||||||
href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
|
href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
|
||||||
imageSrc={
|
imageSrc={`${orgBranding?.fullDomain ?? WEBAPP_URL}/${profile.slug}/avatar.png` || undefined}
|
||||||
`${orgBranding?.fullDomain ?? WEBAPP_URL}/${teamId ? "team/" : ""}${profile.slug}/avatar.png` ||
|
|
||||||
undefined
|
|
||||||
}
|
|
||||||
size="md"
|
size="md"
|
||||||
className="mt-1 inline-flex justify-center"
|
className="mt-1 inline-flex justify-center"
|
||||||
/>
|
/>
|
||||||
@@ -739,7 +737,9 @@ const EventTypeListHeading = ({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{profile?.slug && (
|
{profile?.slug && (
|
||||||
<Link href={`${CAL_URL}/${profile.slug}`} className="text-subtle block text-xs">
|
<Link
|
||||||
|
href={`${orgBranding ? orgBranding.fullDomain : CAL_URL}/${profile.slug}`}
|
||||||
|
className="text-subtle block text-xs">
|
||||||
{`${bookerUrl.replace("https://", "").replace("http://", "")}/${profile.slug}`}
|
{`${bookerUrl.replace("https://", "").replace("http://", "")}/${profile.slug}`}
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
@@ -925,32 +925,35 @@ const EventTypesPage = () => {
|
|||||||
if (searchParams?.get("openIntercom") === "true") {
|
if (searchParams?.get("openIntercom") === "true") {
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
setShowProfileBanner(
|
|
||||||
!!orgBranding && !document.cookie.includes("calcom-profile-banner=1") && !user?.completedOnboarding
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setShowProfileBanner(
|
||||||
|
!!orgBranding && !document.cookie.includes("calcom-profile-banner=1") && !user?.completedOnboarding
|
||||||
|
);
|
||||||
|
}, [orgBranding, user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<ShellMain
|
||||||
|
withoutSeo
|
||||||
|
heading={t("event_types_page_title")}
|
||||||
|
hideHeadingOnMobile
|
||||||
|
subtitle={t("event_types_page_subtitle")}
|
||||||
|
afterHeading={showProfileBanner && <SetupProfileBanner closeAction={closeBanner} />}
|
||||||
|
beforeCTAactions={<Actions />}
|
||||||
|
CTA={<CTA data={data} />}>
|
||||||
<HeadSeo
|
<HeadSeo
|
||||||
title="Event Types"
|
title="Event Types"
|
||||||
description="Create events to share for people to book on your calendar."
|
description="Create events to share for people to book on your calendar."
|
||||||
/>
|
/>
|
||||||
<Shell
|
<Main data={data} status={status} error={error} filters={filters} />
|
||||||
withoutSeo
|
</ShellMain>
|
||||||
heading={t("event_types_page_title")}
|
|
||||||
hideHeadingOnMobile
|
|
||||||
subtitle={t("event_types_page_subtitle")}
|
|
||||||
afterHeading={showProfileBanner && <SetupProfileBanner closeAction={closeBanner} />}
|
|
||||||
beforeCTAactions={<Actions />}
|
|
||||||
CTA={<CTA data={data} />}>
|
|
||||||
<Main data={data} status={status} error={error} filters={filters} />
|
|
||||||
</Shell>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EventTypesPage.getLayout = getLayout;
|
||||||
|
|
||||||
EventTypesPage.PageWrapper = PageWrapper;
|
EventTypesPage.PageWrapper = PageWrapper;
|
||||||
|
|
||||||
export default EventTypesPage;
|
export default EventTypesPage;
|
||||||
@@ -121,10 +121,10 @@ const OnboardingPage = () => {
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<div className="mx-auto px-4 py-6 md:py-24">
|
<div className="mx-auto py-6 sm:px-4 md:py-24">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
||||||
<div className="mx-auto sm:max-w-[520px]">
|
<div className="mx-auto px-4 sm:max-w-[520px]">
|
||||||
<header>
|
<header>
|
||||||
<p className="font-cal mb-3 text-[28px] font-medium leading-7">
|
<p className="font-cal mb-3 text-[28px] font-medium leading-7">
|
||||||
{headers[currentStepIndex]?.title || "Undefined title"}
|
{headers[currentStepIndex]?.title || "Undefined title"}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
import { getFeatureFlagMap } from "@calcom/features/flags/server/utils";
|
import { getFeatureFlagMap } from "@calcom/features/flags/server/utils";
|
||||||
import {
|
import {
|
||||||
AverageEventDurationChart,
|
AverageEventDurationChart,
|
||||||
@@ -9,7 +10,7 @@ import {
|
|||||||
} from "@calcom/features/insights/components";
|
} from "@calcom/features/insights/components";
|
||||||
import { FiltersProvider } from "@calcom/features/insights/context/FiltersProvider";
|
import { FiltersProvider } from "@calcom/features/insights/context/FiltersProvider";
|
||||||
import { Filters } from "@calcom/features/insights/filters";
|
import { Filters } from "@calcom/features/insights/filters";
|
||||||
import Shell from "@calcom/features/shell/Shell";
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { UpgradeTip } from "@calcom/features/tips";
|
import { UpgradeTip } from "@calcom/features/tips";
|
||||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
@@ -56,7 +57,7 @@ export default function InsightsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Shell hideHeadingOnMobile>
|
<ShellMain hideHeadingOnMobile>
|
||||||
<UpgradeTip
|
<UpgradeTip
|
||||||
title={t("make_informed_decisions")}
|
title={t("make_informed_decisions")}
|
||||||
description={t("make_informed_decisions_description")}
|
description={t("make_informed_decisions_description")}
|
||||||
@@ -111,12 +112,13 @@ export default function InsightsPage() {
|
|||||||
</FiltersProvider>
|
</FiltersProvider>
|
||||||
)}
|
)}
|
||||||
</UpgradeTip>
|
</UpgradeTip>
|
||||||
</Shell>
|
</ShellMain>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
InsightsPage.PageWrapper = PageWrapper;
|
InsightsPage.PageWrapper = PageWrapper;
|
||||||
|
InsightsPage.getLayout = getLayout;
|
||||||
|
|
||||||
// If feature flag is disabled, return not found on getServerSideProps
|
// If feature flag is disabled, return not found on getServerSideProps
|
||||||
export const getServerSideProps = async () => {
|
export const getServerSideProps = async () => {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import PageWrapper from "@components/PageWrapper";
|
||||||
|
import { getLayout } from "@components/auth/layouts/AdminLayout";
|
||||||
|
|
||||||
|
import KYCVerificationView from "./kycVerificationView";
|
||||||
|
|
||||||
|
const KYCVerificationPage = () => <KYCVerificationView />;
|
||||||
|
|
||||||
|
KYCVerificationPage.getLayout = getLayout;
|
||||||
|
KYCVerificationPage.PageWrapper = PageWrapper;
|
||||||
|
|
||||||
|
export default KYCVerificationPage;
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
import { trpc } from "@calcom/trpc";
|
||||||
|
import { Meta, Form, Button, TextField, showToast } from "@calcom/ui";
|
||||||
|
|
||||||
|
type FormValues = {
|
||||||
|
name?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function KYCVerificationView() {
|
||||||
|
const teamForm = useForm<FormValues>();
|
||||||
|
const userForm = useForm<FormValues>();
|
||||||
|
|
||||||
|
const mutation = trpc.viewer.kycVerification.verify.useMutation({
|
||||||
|
onSuccess: async (data) => {
|
||||||
|
showToast(`Successfully verified ${data.isTeam ? "team" : "user"} ${data.name}`, "success");
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
showToast(`Verification failed: ${error.message}`, "error");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Meta
|
||||||
|
title="KYC Verification"
|
||||||
|
description="Here you can verify users and teams. This verification is needed for sending sms/whatsapp messages to attendees."
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div className="mb-2 font-medium">Verify Team</div>
|
||||||
|
|
||||||
|
<Form
|
||||||
|
form={teamForm}
|
||||||
|
handleSubmit={(values) => {
|
||||||
|
mutation.mutate({
|
||||||
|
name: values.name || "",
|
||||||
|
isTeam: true,
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<TextField
|
||||||
|
{...teamForm.register("name")}
|
||||||
|
label=""
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
placeholder="team slug"
|
||||||
|
className="-mt-2 "
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<Button type="submit">Verify</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="mb-2 mt-6 font-medium">Verify User</div>
|
||||||
|
<Form
|
||||||
|
form={userForm}
|
||||||
|
handleSubmit={(values) => {
|
||||||
|
mutation.mutate({
|
||||||
|
name: values.name || "",
|
||||||
|
isTeam: false,
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<TextField
|
||||||
|
{...userForm.register("name")}
|
||||||
|
label=""
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
placeholder="user name"
|
||||||
|
className="-mt-2"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<Button type="submit">Verify</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -116,6 +116,7 @@ const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
|
|||||||
label: nameOfDay(localeProp, user.weekStart === "Sunday" ? 0 : 1),
|
label: nameOfDay(localeProp, user.weekStart === "Sunday" ? 0 : 1),
|
||||||
},
|
},
|
||||||
allowDynamicBooking: user.allowDynamicBooking ?? true,
|
allowDynamicBooking: user.allowDynamicBooking ?? true,
|
||||||
|
allowSEOIndexing: user.allowSEOIndexing ?? true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
@@ -124,6 +125,7 @@ const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
|
|||||||
getValues,
|
getValues,
|
||||||
} = formMethods;
|
} = formMethods;
|
||||||
const isDisabled = isSubmitting || !isDirty;
|
const isDisabled = isSubmitting || !isDirty;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
form={formMethods}
|
form={formMethods}
|
||||||
@@ -225,6 +227,24 @@ const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<Controller
|
||||||
|
name="allowSEOIndexing"
|
||||||
|
control={formMethods.control}
|
||||||
|
render={() => (
|
||||||
|
<SettingsToggle
|
||||||
|
title={t("seo_indexing")}
|
||||||
|
description={t("allow_seo_indexing")}
|
||||||
|
checked={formMethods.getValues("allowSEOIndexing")}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
formMethods.setValue("allowSEOIndexing", checked, { shouldDirty: true });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
loading={mutation.isLoading}
|
loading={mutation.isLoading}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|||||||
@@ -77,10 +77,9 @@ type FormValues = {
|
|||||||
const ProfileView = () => {
|
const ProfileView = () => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
const { data: session, update } = useSession();
|
const { data: _session, update } = useSession();
|
||||||
|
|
||||||
const { data: user, isLoading } = trpc.viewer.me.useQuery();
|
const { data: user, isLoading } = trpc.viewer.me.useQuery();
|
||||||
const { data: avatar, isLoading: isLoadingAvatar } = trpc.viewer.avatar.useQuery();
|
|
||||||
const updateProfileMutation = trpc.viewer.updateProfile.useMutation({
|
const updateProfileMutation = trpc.viewer.updateProfile.useMutation({
|
||||||
onSuccess: async (res) => {
|
onSuccess: async (res) => {
|
||||||
showToast(t("settings_updated_successfully"), "success");
|
showToast(t("settings_updated_successfully"), "success");
|
||||||
@@ -205,14 +204,14 @@ const ProfileView = () => {
|
|||||||
[ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"),
|
[ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading || !user || isLoadingAvatar || !avatar)
|
if (isLoading || !user)
|
||||||
return (
|
return (
|
||||||
<SkeletonLoader title={t("profile")} description={t("profile_description", { appName: APP_NAME })} />
|
<SkeletonLoader title={t("profile")} description={t("profile_description", { appName: APP_NAME })} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
username: user.username || "",
|
username: user.username || "",
|
||||||
avatar: avatar.avatar || "",
|
avatar: user.avatar || "",
|
||||||
name: user.name || "",
|
name: user.name || "",
|
||||||
email: user.email || "",
|
email: user.email || "",
|
||||||
bio: user.bio || "",
|
bio: user.bio || "",
|
||||||
|
|||||||
@@ -272,6 +272,9 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
|||||||
username = available ? username : suggestion || username;
|
username = available ? username : suggestion || username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform all + to - in username
|
||||||
|
username = username.replace(/\+/g, "-");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...props,
|
...props,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|||||||
import { Booker } from "@calcom/atoms";
|
import { Booker } from "@calcom/atoms";
|
||||||
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
import { getBookerWrapperClasses } from "@calcom/features/bookings/Booker/utils/getBookerWrapperClasses";
|
||||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||||
import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booking";
|
import { getBookingForReschedule, getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||||
import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
|
import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||||
@@ -18,7 +18,16 @@ import PageWrapper from "@components/PageWrapper";
|
|||||||
|
|
||||||
export type PageProps = inferSSRProps<typeof getServerSideProps> & EmbedProps;
|
export type PageProps = inferSSRProps<typeof getServerSideProps> & EmbedProps;
|
||||||
|
|
||||||
export default function Type({ slug, user, booking, away, isEmbed, isBrandingHidden, entity }: PageProps) {
|
export default function Type({
|
||||||
|
slug,
|
||||||
|
user,
|
||||||
|
booking,
|
||||||
|
away,
|
||||||
|
isEmbed,
|
||||||
|
isBrandingHidden,
|
||||||
|
entity,
|
||||||
|
duration,
|
||||||
|
}: PageProps) {
|
||||||
return (
|
return (
|
||||||
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
|
||||||
<BookerSeo
|
<BookerSeo
|
||||||
@@ -37,6 +46,7 @@ export default function Type({ slug, user, booking, away, isEmbed, isBrandingHid
|
|||||||
hideBranding={isBrandingHidden}
|
hideBranding={isBrandingHidden}
|
||||||
isTeamEvent
|
isTeamEvent
|
||||||
entity={entity}
|
entity={entity}
|
||||||
|
duration={duration}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
@@ -55,7 +65,7 @@ const paramsSchema = z.object({
|
|||||||
// 2. If rescheduling, get the booking details
|
// 2. If rescheduling, get the booking details
|
||||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||||
const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params);
|
const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params);
|
||||||
const { rescheduleUid } = context.query;
|
const { rescheduleUid, duration: queryDuration } = context.query;
|
||||||
const { ssrInit } = await import("@server/lib/ssr");
|
const { ssrInit } = await import("@server/lib/ssr");
|
||||||
const ssr = await ssrInit(context);
|
const ssr = await ssrInit(context);
|
||||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(
|
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(
|
||||||
@@ -104,6 +114,11 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
entity: eventData.entity,
|
entity: eventData.entity,
|
||||||
|
duration: getMultipleDurationValue(
|
||||||
|
eventData.metadata?.multipleDuration,
|
||||||
|
queryDuration,
|
||||||
|
eventData.length
|
||||||
|
),
|
||||||
booking,
|
booking,
|
||||||
away: false,
|
away: false,
|
||||||
user: teamSlug,
|
user: teamSlug,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { GetServerSidePropsContext } from "next";
|
import type { GetServerSidePropsContext } from "next";
|
||||||
|
|
||||||
|
import { getLayout } from "@calcom/features/MainLayout";
|
||||||
import { TeamsListing } from "@calcom/features/ee/teams/components";
|
import { TeamsListing } from "@calcom/features/ee/teams/components";
|
||||||
import Shell from "@calcom/features/shell/Shell";
|
import { ShellMain } from "@calcom/features/shell/Shell";
|
||||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
@@ -17,7 +18,7 @@ function Teams() {
|
|||||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell
|
<ShellMain
|
||||||
heading={t("teams")}
|
heading={t("teams")}
|
||||||
hideHeadingOnMobile
|
hideHeadingOnMobile
|
||||||
subtitle={t("create_manage_teams_collaborative")}
|
subtitle={t("create_manage_teams_collaborative")}
|
||||||
@@ -33,7 +34,7 @@ function Teams() {
|
|||||||
)
|
)
|
||||||
}>
|
}>
|
||||||
<TeamsListing />
|
<TeamsListing />
|
||||||
</Shell>
|
</ShellMain>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,5 +47,5 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
|||||||
|
|
||||||
Teams.requiresLicense = false;
|
Teams.requiresLicense = false;
|
||||||
Teams.PageWrapper = PageWrapper;
|
Teams.PageWrapper = PageWrapper;
|
||||||
|
Teams.getLayout = getLayout;
|
||||||
export default Teams;
|
export default Teams;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
|
import { installAppleCalendar } from "./lib/testUtils";
|
||||||
|
|
||||||
test.describe.configure({ mode: "parallel" });
|
test.describe.configure({ mode: "parallel" });
|
||||||
|
|
||||||
@@ -10,10 +11,9 @@ test.describe("App Store - Authed", () => {
|
|||||||
test("Browse apple-calendar and try to install", async ({ page, users }) => {
|
test("Browse apple-calendar and try to install", async ({ page, users }) => {
|
||||||
const pro = await users.create();
|
const pro = await users.create();
|
||||||
await pro.apiLogin();
|
await pro.apiLogin();
|
||||||
await page.goto("/apps/categories/calendar");
|
|
||||||
await page.click('[data-testid="app-store-app-card-apple-calendar"]');
|
await installAppleCalendar(page);
|
||||||
await page.waitForURL("/apps/apple-calendar");
|
|
||||||
await page.click('[data-testid="install-app-button"]');
|
|
||||||
await expect(page.locator(`text=Connect to Apple Server`)).toBeVisible();
|
await expect(page.locator(`text=Connect to Apple Server`)).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -31,9 +31,8 @@ test.describe("App Store - Authed", () => {
|
|||||||
|
|
||||||
test.describe("App Store - Unauthed", () => {
|
test.describe("App Store - Unauthed", () => {
|
||||||
test("Browse apple-calendar and try to install", async ({ page }) => {
|
test("Browse apple-calendar and try to install", async ({ page }) => {
|
||||||
await page.goto("/apps/categories/calendar");
|
await installAppleCalendar(page);
|
||||||
await page.click('[data-testid="app-store-app-card-apple-calendar"]');
|
|
||||||
await page.click('[data-testid="install-app-button"]');
|
|
||||||
await expect(page.locator(`[data-testid="login-form"]`)).toBeVisible();
|
await expect(page.locator(`[data-testid="login-form"]`)).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
|
import { test } from "./lib/fixtures";
|
||||||
|
import { installAppleCalendar } from "./lib/testUtils";
|
||||||
|
|
||||||
|
test.describe.configure({ mode: "parallel" });
|
||||||
|
|
||||||
|
test.afterEach(({ users }) => users.deleteAll());
|
||||||
|
|
||||||
|
const APPLE_CALENDAR_EMAIL = process.env.E2E_TEST_APPLE_CALENDAR_EMAIL!;
|
||||||
|
const APPLE_CALENDAR_PASSWORD = process.env.E2E_TEST_APPLE_CALENDAR_PASSWORD!;
|
||||||
|
|
||||||
|
const SHOULD_SKIP_TESTS = !APPLE_CALENDAR_EMAIL || !APPLE_CALENDAR_PASSWORD;
|
||||||
|
|
||||||
|
test.describe("Apple Calendar", () => {
|
||||||
|
// eslint-disable-next-line playwright/no-skipped-test
|
||||||
|
test.skip(SHOULD_SKIP_TESTS, "Skipping due to missing the testing credentials");
|
||||||
|
|
||||||
|
test("Should be able to install and login on Apple Calendar", async ({ page, users }) => {
|
||||||
|
const user = await users.create();
|
||||||
|
await user.apiLogin();
|
||||||
|
|
||||||
|
await installAppleCalendar(page);
|
||||||
|
|
||||||
|
await expect(page.locator('[data-testid="apple-calendar-form"]')).toBeVisible();
|
||||||
|
|
||||||
|
await page.fill('[data-testid="apple-calendar-email"]', APPLE_CALENDAR_EMAIL);
|
||||||
|
await page.fill('[data-testid="apple-calendar-password"]', APPLE_CALENDAR_PASSWORD);
|
||||||
|
await page.click('[data-testid="apple-calendar-login-button"]');
|
||||||
|
|
||||||
|
await expect(page.getByText("Apple Calendar")).toBeVisible();
|
||||||
|
await expect(page.getByText(APPLE_CALENDAR_EMAIL)).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
|
import type { Messages } from "mailhog";
|
||||||
|
|
||||||
|
import { randomString } from "@calcom/lib/random";
|
||||||
|
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
import {
|
import {
|
||||||
@@ -10,30 +13,47 @@ import {
|
|||||||
testName,
|
testName,
|
||||||
} from "./lib/testUtils";
|
} from "./lib/testUtils";
|
||||||
|
|
||||||
|
const freeUserObj = { name: `Free-user-${randomString(3)}` };
|
||||||
test.describe.configure({ mode: "parallel" });
|
test.describe.configure({ mode: "parallel" });
|
||||||
test.afterEach(async ({ users }) => users.deleteAll());
|
test.afterEach(async ({ users }) => {
|
||||||
|
await users.deleteAll();
|
||||||
|
});
|
||||||
|
|
||||||
test.describe("free user", () => {
|
test.describe("free user", () => {
|
||||||
test.beforeEach(async ({ page, users }) => {
|
test.beforeEach(async ({ page, users }) => {
|
||||||
const free = await users.create();
|
const free = await users.create(freeUserObj);
|
||||||
await page.goto(`/${free.username}`);
|
await page.goto(`/${free.username}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("cannot book same slot multiple times", async ({ page }) => {
|
test("cannot book same slot multiple times", async ({ page, users, emails }) => {
|
||||||
|
const [user] = users.get();
|
||||||
|
const bookerObj = { email: `testEmail-${randomString(4)}@example.com`, name: "testBooker" };
|
||||||
// Click first event type
|
// Click first event type
|
||||||
await page.click('[data-testid="event-type-link"]');
|
await page.click('[data-testid="event-type-link"]');
|
||||||
|
|
||||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||||
|
|
||||||
await bookTimeSlot(page);
|
await bookTimeSlot(page, bookerObj);
|
||||||
|
|
||||||
// save booking url
|
// save booking url
|
||||||
const bookingUrl: string = page.url();
|
const bookingUrl: string = page.url();
|
||||||
|
|
||||||
// Make sure we're navigated to the success page
|
// Make sure we're navigated to the success page
|
||||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||||
|
const { title: eventTitle } = await user.getFirstEventAsOwner();
|
||||||
|
// TODO: follow DRY
|
||||||
|
const emailsOrganiserReceived = await emails.search(user.email, "to");
|
||||||
|
const emailsBookerReceived = await emails.search(bookerObj.email, "to");
|
||||||
|
expect(emailsOrganiserReceived?.total).toBe(1);
|
||||||
|
expect(emailsBookerReceived?.total).toBe(1);
|
||||||
|
|
||||||
|
const [organizerFirstEmail] = (emailsOrganiserReceived as Messages).items;
|
||||||
|
const [bookerFirstEmail] = (emailsBookerReceived as Messages).items;
|
||||||
|
const emailSubject = `${eventTitle} between ${user.name} and ${bookerObj.name}`;
|
||||||
|
|
||||||
|
expect(organizerFirstEmail.subject).toBe(emailSubject);
|
||||||
|
expect(bookerFirstEmail.subject).toBe(emailSubject);
|
||||||
|
|
||||||
// return to same time spot booking page
|
|
||||||
await page.goto(bookingUrl);
|
await page.goto(bookingUrl);
|
||||||
|
|
||||||
// book same time spot again
|
// book same time spot again
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import {
|
|||||||
|
|
||||||
test.afterEach(({ users }) => users.deleteAll());
|
test.afterEach(({ users }) => users.deleteAll());
|
||||||
|
|
||||||
// Due to some reason for Dynamic booking cancellation, daily video api_key is not set which causes cancellation to fail.
|
test("dynamic booking", async ({ page, users }) => {
|
||||||
// This test is skipped until the issue is resolved in GH actions.
|
|
||||||
// eslint-disable-next-line playwright/no-skipped-test
|
|
||||||
test.skip("dynamic booking", async ({ page, users }) => {
|
|
||||||
const pro = await users.create();
|
const pro = await users.create();
|
||||||
await pro.apiLogin();
|
await pro.apiLogin();
|
||||||
|
|
||||||
@@ -20,10 +17,13 @@ test.skip("dynamic booking", async ({ page, users }) => {
|
|||||||
await page.goto(`/${pro.username}+${free.username}`);
|
await page.goto(`/${pro.username}+${free.username}`);
|
||||||
|
|
||||||
await test.step("book an event first day in next month", async () => {
|
await test.step("book an event first day in next month", async () => {
|
||||||
// Click first event type
|
|
||||||
await page.click('[data-testid="event-type-link"]');
|
|
||||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||||
|
|
||||||
|
// Fill what is this meeting about? title
|
||||||
|
await page.locator('[name="title"]').fill("Test meeting");
|
||||||
|
|
||||||
await bookTimeSlot(page);
|
await bookTimeSlot(page);
|
||||||
|
|
||||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,7 +37,8 @@ test.skip("dynamic booking", async ({ page, users }) => {
|
|||||||
return !!bookingId;
|
return !!bookingId;
|
||||||
});
|
});
|
||||||
await selectSecondAvailableTimeSlotNextMonth(page);
|
await selectSecondAvailableTimeSlotNextMonth(page);
|
||||||
// --- fill form
|
|
||||||
|
// No need to fill fields since they should be already filled
|
||||||
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
||||||
await page.waitForURL((url) => {
|
await page.waitForURL((url) => {
|
||||||
return url.pathname.startsWith("/booking");
|
return url.pathname.startsWith("/booking");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Page, WorkerInfo } from "@playwright/test";
|
|||||||
import type Prisma from "@prisma/client";
|
import type Prisma from "@prisma/client";
|
||||||
import { Prisma as PrismaType } from "@prisma/client";
|
import { Prisma as PrismaType } from "@prisma/client";
|
||||||
import { hashSync as hash } from "bcryptjs";
|
import { hashSync as hash } from "bcryptjs";
|
||||||
|
import type { API } from "mailhog";
|
||||||
|
|
||||||
import dayjs from "@calcom/dayjs";
|
import dayjs from "@calcom/dayjs";
|
||||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||||
@@ -116,7 +117,7 @@ const createTeamAndAddUser = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
// creates a user fixture instance and stores the collection
|
// creates a user fixture instance and stores the collection
|
||||||
export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
|
export const createUsersFixture = (page: Page, emails: API, workerInfo: WorkerInfo) => {
|
||||||
const store = { users: [], page } as { users: UserFixture[]; page: typeof page };
|
const store = { users: [], page } as { users: UserFixture[]; page: typeof page };
|
||||||
return {
|
return {
|
||||||
create: async (
|
create: async (
|
||||||
@@ -330,7 +331,19 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
|
|||||||
await page.goto("/auth/logout");
|
await page.goto("/auth/logout");
|
||||||
},
|
},
|
||||||
deleteAll: async () => {
|
deleteAll: async () => {
|
||||||
|
const emailMessageIds: string[] = [];
|
||||||
const ids = store.users.map((u) => u.id);
|
const ids = store.users.map((u) => u.id);
|
||||||
|
for (const user of store.users) {
|
||||||
|
const emailMessages = await emails.search(user.email);
|
||||||
|
if (emailMessages && emailMessages.count > 0) {
|
||||||
|
emailMessages.items.forEach((item) => {
|
||||||
|
emailMessageIds.push(item.ID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const id of emailMessageIds) {
|
||||||
|
await emails.deleteMessage(id);
|
||||||
|
}
|
||||||
await prisma.user.deleteMany({ where: { id: { in: ids } } });
|
await prisma.user.deleteMany({ where: { id: { in: ids } } });
|
||||||
store.users = [];
|
store.users = [];
|
||||||
},
|
},
|
||||||
@@ -387,6 +400,12 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => {
|
|||||||
include: { team: { select: { children: true, metadata: true, name: true } } },
|
include: { team: { select: { children: true, metadata: true, name: true } } },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getFirstEventAsOwner: async () =>
|
||||||
|
prisma.eventType.findFirstOrThrow({
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
getFirstTeamEvent: async (teamId: number) => {
|
getFirstTeamEvent: async (teamId: number) => {
|
||||||
return prisma.eventType.findFirstOrThrow({
|
return prisma.eventType.findFirstOrThrow({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import type { Page } from "@playwright/test";
|
import type { Page } from "@playwright/test";
|
||||||
import { test as base } from "@playwright/test";
|
import { test as base } from "@playwright/test";
|
||||||
|
import type { API } from "mailhog";
|
||||||
|
import mailhog from "mailhog";
|
||||||
|
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
|
|
||||||
@@ -19,6 +21,7 @@ export interface Fixtures {
|
|||||||
getActionFiredDetails: ReturnType<typeof createGetActionFiredDetails>;
|
getActionFiredDetails: ReturnType<typeof createGetActionFiredDetails>;
|
||||||
servers: ReturnType<typeof createServersFixture>;
|
servers: ReturnType<typeof createServersFixture>;
|
||||||
prisma: typeof prisma;
|
prisma: typeof prisma;
|
||||||
|
emails: API;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -40,8 +43,8 @@ declare global {
|
|||||||
* @see https://playwright.dev/docs/test-fixtures
|
* @see https://playwright.dev/docs/test-fixtures
|
||||||
*/
|
*/
|
||||||
export const test = base.extend<Fixtures>({
|
export const test = base.extend<Fixtures>({
|
||||||
users: async ({ page, context }, use, workerInfo) => {
|
users: async ({ page, context, emails }, use, workerInfo) => {
|
||||||
const usersFixture = createUsersFixture(page, workerInfo);
|
const usersFixture = createUsersFixture(page, emails, workerInfo);
|
||||||
await use(usersFixture);
|
await use(usersFixture);
|
||||||
},
|
},
|
||||||
bookings: async ({ page }, use) => {
|
bookings: async ({ page }, use) => {
|
||||||
@@ -67,4 +70,8 @@ export const test = base.extend<Fixtures>({
|
|||||||
prisma: async ({}, use) => {
|
prisma: async ({}, use) => {
|
||||||
await use(prisma);
|
await use(prisma);
|
||||||
},
|
},
|
||||||
|
emails: async ({}, use) => {
|
||||||
|
const mailhogAPI = mailhog();
|
||||||
|
await use(mailhogAPI);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
@@ -183,3 +183,10 @@ export async function gotoRoutingLink({
|
|||||||
// HACK: There seems to be some issue with the inputs to the form getting reset if we don't wait.
|
// HACK: There seems to be some issue with the inputs to the form getting reset if we don't wait.
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function installAppleCalendar(page: Page) {
|
||||||
|
await page.goto("/apps/categories/calendar");
|
||||||
|
await page.click('[data-testid="app-store-app-card-apple-calendar"]');
|
||||||
|
await page.waitForURL("/apps/apple-calendar");
|
||||||
|
await page.click('[data-testid="install-app-button"]');
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { expect } from "@playwright/test";
|
|||||||
import { authenticator } from "otplib";
|
import { authenticator } from "otplib";
|
||||||
|
|
||||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||||
|
import { totpAuthenticatorCheck } from "@calcom/lib/totp";
|
||||||
|
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
|
|
||||||
@@ -141,7 +142,7 @@ test.describe("2FA Tests", async () => {
|
|||||||
|
|
||||||
async function fillOtp({ page, secret, noRetry }: { page: Page; secret: string; noRetry?: boolean }) {
|
async function fillOtp({ page, secret, noRetry }: { page: Page; secret: string; noRetry?: boolean }) {
|
||||||
let token = authenticator.generate(secret);
|
let token = authenticator.generate(secret);
|
||||||
if (!noRetry && !authenticator.check(token, secret)) {
|
if (!noRetry && !totpAuthenticatorCheck(token, secret)) {
|
||||||
console.log("Token expired, Renerating.");
|
console.log("Token expired, Renerating.");
|
||||||
// Maybe token was just about to expire, try again just once more
|
// Maybe token was just about to expire, try again just once more
|
||||||
token = authenticator.generate(secret);
|
token = authenticator.generate(secret);
|
||||||
|
|||||||
@@ -316,8 +316,6 @@ async function runTestStepsCommonForTeamAndUserEventType(
|
|||||||
await test.step("Do a reschedule and notice that we can't book without giving a value for rescheduleReason", async () => {
|
await test.step("Do a reschedule and notice that we can't book without giving a value for rescheduleReason", async () => {
|
||||||
const page = previewTabPage;
|
const page = previewTabPage;
|
||||||
await rescheduleFromTheLinkOnPage({ page });
|
await rescheduleFromTheLinkOnPage({ page });
|
||||||
// eslint-disable-next-line playwright/no-page-pause
|
|
||||||
await page.pause();
|
|
||||||
await expectErrorToBeThereFor({ page, name: "rescheduleReason" });
|
await expectErrorToBeThereFor({ page, name: "rescheduleReason" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
|
import dayjs from "@calcom/dayjs";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { BookingStatus } from "@calcom/prisma/enums";
|
import { BookingStatus } from "@calcom/prisma/enums";
|
||||||
|
|
||||||
@@ -239,4 +240,33 @@ test.describe("Reschedule Tests", async () => {
|
|||||||
expect(newBooking).not.toBeNull();
|
expect(newBooking).not.toBeNull();
|
||||||
expect(newBooking?.status).toBe(BookingStatus.ACCEPTED);
|
expect(newBooking?.status).toBe(BookingStatus.ACCEPTED);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Should be able to book slot that overlaps with original rescheduled booking", async ({
|
||||||
|
page,
|
||||||
|
users,
|
||||||
|
bookings,
|
||||||
|
}) => {
|
||||||
|
const user = await users.create();
|
||||||
|
const eventType = user.eventTypes[0];
|
||||||
|
|
||||||
|
let firstOfNextMonth = dayjs().add(1, "month").startOf("month");
|
||||||
|
|
||||||
|
// find first available slot of next month (available monday-friday)
|
||||||
|
while (firstOfNextMonth.day() < 1 || firstOfNextMonth.day() > 5) {
|
||||||
|
firstOfNextMonth = firstOfNextMonth.add(1, "day");
|
||||||
|
}
|
||||||
|
|
||||||
|
// set startTime to first available slot
|
||||||
|
const startTime = firstOfNextMonth.set("hour", 9).set("minute", 0).toDate();
|
||||||
|
const endTime = firstOfNextMonth.set("hour", 9).set("minute", 30).toDate();
|
||||||
|
|
||||||
|
const booking = await bookings.create(user.id, user.username, eventType.id, {}, startTime, endTime);
|
||||||
|
|
||||||
|
await page.goto(`/reschedule/${booking.uid}`);
|
||||||
|
|
||||||
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||||
|
|
||||||
|
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
||||||
|
await expect(page).toHaveURL(/.*booking/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
"upgrade_banner_action": "Hier aufrüsten",
|
"upgrade_banner_action": "Hier aufrüsten",
|
||||||
"team_upgraded_successfully": "Das Update für Ihr Team war erfolgreich!",
|
"team_upgraded_successfully": "Das Update für Ihr Team war erfolgreich!",
|
||||||
"org_upgrade_banner_description": "Vielen Dank, dass Sie unseren neuen Organisationsplan getestet haben. Wir haben festgestellt, dass Ihre Organisation „{{teamName}}“ ein Upgrade benötigt.",
|
"org_upgrade_banner_description": "Vielen Dank, dass Sie unseren neuen Organisationsplan getestet haben. Wir haben festgestellt, dass Ihre Organisation „{{teamName}}“ ein Upgrade benötigt.",
|
||||||
"org_upgraded_successfully": "Das Update für Ihre Organisation war erfolgreich!",
|
"org_upgraded_successfully": "Das Update für Ihre Organization war erfolgreich!",
|
||||||
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
|
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
|
||||||
"hey_there": "Hallo,",
|
"hey_there": "Hallo,",
|
||||||
"forgot_your_password_calcom": "Passwort vergessen? - {{appName}}",
|
"forgot_your_password_calcom": "Passwort vergessen? - {{appName}}",
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
"blog": "Blog",
|
"blog": "Blog",
|
||||||
"blog_description": "Lesen Sie unsere Neuigkeiten und Artikel",
|
"blog_description": "Lesen Sie unsere Neuigkeiten und Artikel",
|
||||||
"join_our_community": "Treten Sie unserer Community bei",
|
"join_our_community": "Treten Sie unserer Community bei",
|
||||||
"join_our_discord": "Treten Sie unserem Discord-Server bei",
|
"join_our_discord": "Treffe uns im Discord",
|
||||||
"404_claim_entity_user": "Benutzername registrieren und Termine vergeben",
|
"404_claim_entity_user": "Benutzername registrieren und Termine vergeben",
|
||||||
"popular_pages": "Beliebte Seiten",
|
"popular_pages": "Beliebte Seiten",
|
||||||
"register_now": "Jetzt registrieren",
|
"register_now": "Jetzt registrieren",
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
"bookerlayout_user_settings_title": "Buchungslayout",
|
"bookerlayout_user_settings_title": "Buchungslayout",
|
||||||
"bookerlayout_user_settings_description": "Sie können mehrere auswählen und Bucher können die Ansicht wechseln. Dies kann pro Termin überschrieben werden.",
|
"bookerlayout_user_settings_description": "Sie können mehrere auswählen und Bucher können die Ansicht wechseln. Dies kann pro Termin überschrieben werden.",
|
||||||
"bookerlayout_month_view": "Monat",
|
"bookerlayout_month_view": "Monat",
|
||||||
"bookerlayout_week_view": "Woche",
|
"bookerlayout_week_view": "Wöchentlich",
|
||||||
"bookerlayout_column_view": "Spalte",
|
"bookerlayout_column_view": "Spalte",
|
||||||
"bookerlayout_error_min_one_enabled": "Es muss mindestens ein Layout aktiviert sein.",
|
"bookerlayout_error_min_one_enabled": "Es muss mindestens ein Layout aktiviert sein.",
|
||||||
"bookerlayout_error_default_not_enabled": "Das Layout, das Sie als Standardansicht ausgewählt haben, ist nicht Teil der aktivierten Layouts.",
|
"bookerlayout_error_default_not_enabled": "Das Layout, das Sie als Standardansicht ausgewählt haben, ist nicht Teil der aktivierten Layouts.",
|
||||||
@@ -404,6 +404,8 @@
|
|||||||
"allow_dynamic_booking_tooltip": "Gruppenbuchungslinks, die dynamisch durch Hinzufügen mehrerer Benutzernamen mit einem '+' erstellt werden können. Beispiel: '{{appName}}/bailey+peer'",
|
"allow_dynamic_booking_tooltip": "Gruppenbuchungslinks, die dynamisch durch Hinzufügen mehrerer Benutzernamen mit einem '+' erstellt werden können. Beispiel: '{{appName}}/bailey+peer'",
|
||||||
"allow_dynamic_booking": "Ermöglichen Sie es den Teilnehmenden, Sie über dynamische Gruppenbuchungen zu buchen",
|
"allow_dynamic_booking": "Ermöglichen Sie es den Teilnehmenden, Sie über dynamische Gruppenbuchungen zu buchen",
|
||||||
"dynamic_booking": "Dynamische Gruppenlinks",
|
"dynamic_booking": "Dynamische Gruppenlinks",
|
||||||
|
"allow_seo_indexing": "Suchmaschinen erlauben, auf Ihre öffentlichen Inhalte zuzugreifen",
|
||||||
|
"seo_indexing": "Suchmaschinen-Indexierung erlauben",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"email_placeholder": "max@example.com",
|
"email_placeholder": "max@example.com",
|
||||||
"full_name": "Vollständiger Name",
|
"full_name": "Vollständiger Name",
|
||||||
@@ -565,7 +567,7 @@
|
|||||||
"team_description": "Ein paar Sätze über Ihr Team auf der öffentlichen Teamseite.",
|
"team_description": "Ein paar Sätze über Ihr Team auf der öffentlichen Teamseite.",
|
||||||
"org_description": "Ein paar Sätze zu Ihrer Organisation. Dies wird auf der URL-Seite Ihrer Organisation erscheinen.",
|
"org_description": "Ein paar Sätze zu Ihrer Organisation. Dies wird auf der URL-Seite Ihrer Organisation erscheinen.",
|
||||||
"members": "Mitglieder",
|
"members": "Mitglieder",
|
||||||
"organization_members": "Organisationsmitglieder",
|
"organization_members": "Mitglieder der Organization",
|
||||||
"member": "Mitglied",
|
"member": "Mitglied",
|
||||||
"number_member_one": "{{count}} Mitglied",
|
"number_member_one": "{{count}} Mitglied",
|
||||||
"number_member_other": "{{count}} Mitglieder",
|
"number_member_other": "{{count}} Mitglieder",
|
||||||
@@ -600,7 +602,7 @@
|
|||||||
"confirm_all": "Alle bestätigen",
|
"confirm_all": "Alle bestätigen",
|
||||||
"disband_team": "Team auflösen",
|
"disband_team": "Team auflösen",
|
||||||
"disband_team_confirmation_message": "Bist du sicher, dass du dieses Team auflösen möchtest? Jeder der diesen Team-Link erhalten hat, kann Sie nicht mehr buchen.",
|
"disband_team_confirmation_message": "Bist du sicher, dass du dieses Team auflösen möchtest? Jeder der diesen Team-Link erhalten hat, kann Sie nicht mehr buchen.",
|
||||||
"disband_org": "Organisation auflösen",
|
"disband_org": "Organization auflösen",
|
||||||
"disband_org_confirmation_message": "Sind Sie sicher, dass Sie diese Organisation auflösen möchten? Alle Teams und Mitglieder werden gelöscht.",
|
"disband_org_confirmation_message": "Sind Sie sicher, dass Sie diese Organisation auflösen möchten? Alle Teams und Mitglieder werden gelöscht.",
|
||||||
"remove_member_confirmation_message": "Sind Sie sicher, dass Sie dieses Mitglied aus dem Team entfernen möchten?",
|
"remove_member_confirmation_message": "Sind Sie sicher, dass Sie dieses Mitglied aus dem Team entfernen möchten?",
|
||||||
"confirm_disband_team": "Ja, Team auflösen",
|
"confirm_disband_team": "Ja, Team auflösen",
|
||||||
@@ -713,7 +715,7 @@
|
|||||||
"create_team_to_get_started": "Erstellen Sie ein Team um loszulegen",
|
"create_team_to_get_started": "Erstellen Sie ein Team um loszulegen",
|
||||||
"teams": "Teams",
|
"teams": "Teams",
|
||||||
"team": "Team",
|
"team": "Team",
|
||||||
"organization": "Organisation",
|
"organization": "Organization",
|
||||||
"team_billing": "Abrechnung der Teams",
|
"team_billing": "Abrechnung der Teams",
|
||||||
"team_billing_description": "Verwalte die Abrechungen deines Teams",
|
"team_billing_description": "Verwalte die Abrechungen deines Teams",
|
||||||
"upgrade_to_flexible_pro_title": "Wir haben die Abrechnung für Teams geändert",
|
"upgrade_to_flexible_pro_title": "Wir haben die Abrechnung für Teams geändert",
|
||||||
@@ -1351,9 +1353,9 @@
|
|||||||
"event_one": "Ereignis",
|
"event_one": "Ereignis",
|
||||||
"event_other": "Ereignisse",
|
"event_other": "Ereignisse",
|
||||||
"profile_team_description": "Einstellungen für Ihr Teamprofil verwalten",
|
"profile_team_description": "Einstellungen für Ihr Teamprofil verwalten",
|
||||||
"profile_org_description": "Einstellungen für Ihr Organisationsprofil verwalten",
|
"profile_org_description": "Einstellungen für Ihr Organization-Profil verwalten",
|
||||||
"members_team_description": "Benutzer in der Gruppe",
|
"members_team_description": "Benutzer in der Gruppe",
|
||||||
"organization_description": "Administratoren und Mitglieder in Ihrer Organisation verwalten",
|
"organization_description": "Administratoren und Mitglieder in Ihrer Organization verwalten",
|
||||||
"team_url": "Team-URL",
|
"team_url": "Team-URL",
|
||||||
"team_members": "Teammitglieder",
|
"team_members": "Teammitglieder",
|
||||||
"more": "Mehr",
|
"more": "Mehr",
|
||||||
@@ -1499,7 +1501,7 @@
|
|||||||
"yearly": "Jährlich",
|
"yearly": "Jährlich",
|
||||||
"checkout": "Kasse",
|
"checkout": "Kasse",
|
||||||
"your_team_disbanded_successfully": "Ihr Team wurde erfolgreich aufgelöst",
|
"your_team_disbanded_successfully": "Ihr Team wurde erfolgreich aufgelöst",
|
||||||
"your_org_disbanded_successfully": "Ihre Organisation wurde erfolgreich aufgelöst",
|
"your_org_disbanded_successfully": "Ihre Organization wurde erfolgreich aufgelöst",
|
||||||
"error_creating_team": "Fehler beim Erstellen des Teams",
|
"error_creating_team": "Fehler beim Erstellen des Teams",
|
||||||
"you": "Sie",
|
"you": "Sie",
|
||||||
"resend_email": "E-Mail erneut senden",
|
"resend_email": "E-Mail erneut senden",
|
||||||
@@ -1896,34 +1898,35 @@
|
|||||||
"first_event_type_webhook_description": "Erstellen Sie Ihren ersten Webhook für diesen Termintypen",
|
"first_event_type_webhook_description": "Erstellen Sie Ihren ersten Webhook für diesen Termintypen",
|
||||||
"install_app_on": "App installieren auf",
|
"install_app_on": "App installieren auf",
|
||||||
"create_for": "Erstellen für",
|
"create_for": "Erstellen für",
|
||||||
"setup_organization": "Eine Organisation einrichten",
|
"currency": "Währung",
|
||||||
"organization_banner_description": "Schaffen Sie eine Umgebung, in der Teams gemeinsame Apps, Workflows und Termintypen mit Round Robin und kollektiver Terminplanung erstellen können.",
|
"setup_organization": "Eine Organization einrichten",
|
||||||
"organization_banner_title": "Verwalten Sie Organisationen mit mehreren Teams",
|
"organization_banner_description": "Schaffen Sie Umgebungen, in der Teams gemeinsame Apps, Workflows und Termintypen mit Round Robin und kollektiver Terminplanung erstellen können.",
|
||||||
"set_up_your_organization": "Ihre Organisation einrichten",
|
"organization_banner_title": "Verwalten Sie Organizations mit mehreren Teams",
|
||||||
"organizations_description": "Organisationen sind geteilte Umgebungen, in denen Teams gemeinsame Termintypen, Apps, Workflows und mehr erstellen können.",
|
"set_up_your_organization": "Ihre Organization einrichten",
|
||||||
"must_enter_organization_name": "Es muss ein Organisationsname eingegeben werden",
|
"organizations_description": "Organizations sind geteilte Umgebungen, in denen Teams gemeinsame Termintypen, Apps, Workflows und mehr erstellen können.",
|
||||||
"must_enter_organization_admin_email": "Sie müssen Ihre Organisations-Mailadresse eingeben",
|
"must_enter_organization_name": "Es muss ein Name für die Organization eingegeben werden",
|
||||||
"admin_email": "Ihre Organisations-E-Mail-Adresse",
|
"must_enter_organization_admin_email": "Sie müssen Ihre Organization-Mailadresse eingeben\n",
|
||||||
|
"admin_email": "Ihre Organization-E-Mail-Adresse",
|
||||||
"admin_username": "Benutzername des Administrators",
|
"admin_username": "Benutzername des Administrators",
|
||||||
"organization_name": "Name der Organisation",
|
"organization_name": "Name der Organization",
|
||||||
"organization_url": "URL der Organisation",
|
"organization_url": "URL der Organization ",
|
||||||
"organization_verify_header": "Bestätigen Sie Ihre Organisations-Mailadresse",
|
"organization_verify_header": "Bestätigen Sie Ihre Organization-Mailadresse",
|
||||||
"organization_verify_email_body": "Bitte verwenden Sie den folgenden Code, um Ihre E-Mail-Adresse zu bestätigen, um die Einrichtung Ihrer Organisation fortzusetzen.",
|
"organization_verify_email_body": "Bitte verwenden Sie den folgenden Code, um Ihre E-Mail-Adresse zu bestätigen, um die Einrichtung Ihrer Organization fortzusetzen.",
|
||||||
"additional_url_parameters": "Zusätzliche URL-Parameter",
|
"additional_url_parameters": "Zusätzliche URL-Parameter",
|
||||||
"about_your_organization": "Über Ihre Organisation",
|
"about_your_organization": "Über Ihre Organization",
|
||||||
"about_your_organization_description": "Organisationen sind geteilte Umgebungen, in denen Sie mehrere Teams mit gemeinsamen Mitgliedern, Termintypen, Apps, Workflows und mehr erstellen können.",
|
"about_your_organization_description": "Organizations sind geteilte Umgebungen, in denen Sie mehrere Teams mit gemeinsamen Mitgliedern, Termintypen, Apps, Workflows und mehr erstellen können.\n",
|
||||||
"create_your_teams": "Erstellen Sie Ihre Teams",
|
"create_your_teams": "Erstellen Sie Ihre Teams",
|
||||||
"create_your_teams_description": "Fangen Sie an, gemeinsam zu planen, indem Sie Ihre Teammitglieder zu Ihrer Organisation hinzufügen",
|
"create_your_teams_description": "Fangen Sie an, gemeinsam zu planen, indem Sie Ihre Teammitglieder zu Ihrer Organization hinzufügen",
|
||||||
"invite_organization_admins": "Laden Sie die Administratoren Ihrer Organisation ein",
|
"invite_organization_admins": "Laden Sie die Administratoren Ihrer Organization ein",
|
||||||
"invite_organization_admins_description": "Diese Administratoren haben Zugriff auf alle Teams in Ihrer Organisation. Sie können Team-Administratoren und -mitglieder später hinzufügen.",
|
"invite_organization_admins_description": "Diese Administratoren haben Zugriff auf alle Teams in Ihrer Organization. Sie können Team-Administratoren und -mitglieder später hinzufügen.",
|
||||||
"set_a_password": "Legen Sie ein Passwort fest",
|
"set_a_password": "Legen Sie ein Passwort fest",
|
||||||
"set_a_password_description": "Dies wird ein neues Benutzerkonto mit Ihrer Organisations-Mailadresse und diesem Passwort erstellen.",
|
"set_a_password_description": "Dies wird ein neues Benutzerkonto mit Ihrer Organization-Mailadresse und diesem Passwort erstellen.",
|
||||||
"organization_logo": "Logo der Organisation",
|
"organization_logo": "Logo der Organization",
|
||||||
"organization_about_description": "Ein paar Sätze zu Ihrer Organisation. Dies wird auf der öffentlichen Profilseite Ihrer Organisation erscheinen.",
|
"organization_about_description": "Ein paar Sätze zu Ihrer Organization. Dies wird auf der öffentlichen Profilseite Ihrer Organization erscheinen.",
|
||||||
"ill_do_this_later": "Ich werde das später tun",
|
"ill_do_this_later": "Ich werde das später tun",
|
||||||
"verify_your_email": "Bestätigen Sie Ihre E-Mail",
|
"verify_your_email": "Bestätigen Sie Ihre E-Mail",
|
||||||
"enter_digit_code": "Geben Sie den 6-stelligen Code ein, den wir an {{email}} gesendet haben",
|
"enter_digit_code": "Geben Sie den 6-stelligen Code ein, den wir an {{email}} gesendet haben",
|
||||||
"verify_email_organization": "Bestätigen Sie Ihre E-Mail, um eine Organisation zu erstellen",
|
"verify_email_organization": "Bestätigen Sie Ihre E-Mail, um eine Organization zu erstellen",
|
||||||
"code_provided_invalid": "Der eingegebene Code ist ungültig, versuchen Sie es erneut",
|
"code_provided_invalid": "Der eingegebene Code ist ungültig, versuchen Sie es erneut",
|
||||||
"email_already_used": "Die E-Mail-Adresse wird bereits verwendet",
|
"email_already_used": "Die E-Mail-Adresse wird bereits verwendet",
|
||||||
"organization_admin_invited_heading": "Sie wurden eingeladen, ein Mitglied von {{orgName}} zu werden",
|
"organization_admin_invited_heading": "Sie wurden eingeladen, ein Mitglied von {{orgName}} zu werden",
|
||||||
@@ -1931,8 +1934,8 @@
|
|||||||
"duplicated_slugs_warning": "Die folgenden Teams konnten aufgrund von doppelten Slugs nicht erstellt werden: {{slugs}}",
|
"duplicated_slugs_warning": "Die folgenden Teams konnten aufgrund von doppelten Slugs nicht erstellt werden: {{slugs}}",
|
||||||
"team_names_empty": "Teamnamen dürfen nicht leer sein",
|
"team_names_empty": "Teamnamen dürfen nicht leer sein",
|
||||||
"team_names_repeated": "Teamnamen dürfen nicht wiederholt vorkommen",
|
"team_names_repeated": "Teamnamen dürfen nicht wiederholt vorkommen",
|
||||||
"user_belongs_organization": "Der Benutzer gehört einer Organisation an",
|
"user_belongs_organization": "Der Benutzer gehört einer Organization an",
|
||||||
"org_no_teams_yet": "Diese Organisation hat noch keine Teams",
|
"org_no_teams_yet": "Diese Organization hat noch keine Teams",
|
||||||
"org_no_teams_yet_description": "Falls Sie ein Administrator sind, sollten Sie unbedingt Teams erstellen, welche hier angezeigt werden können.",
|
"org_no_teams_yet_description": "Falls Sie ein Administrator sind, sollten Sie unbedingt Teams erstellen, welche hier angezeigt werden können.",
|
||||||
"set_up": "Einrichten",
|
"set_up": "Einrichten",
|
||||||
"set_up_your_profile": "Richten Sie Ihr Profil ein",
|
"set_up_your_profile": "Richten Sie Ihr Profil ein",
|
||||||
@@ -1942,16 +1945,16 @@
|
|||||||
"crm": "CRM",
|
"crm": "CRM",
|
||||||
"messaging": "Nachrichten",
|
"messaging": "Nachrichten",
|
||||||
"sender_id_info": "Name oder Nummer, welcher bzw. welche als Absender einer SMS angezeigt wird (einige Länder erlauben keine alphanumerischen Absender-IDs)",
|
"sender_id_info": "Name oder Nummer, welcher bzw. welche als Absender einer SMS angezeigt wird (einige Länder erlauben keine alphanumerischen Absender-IDs)",
|
||||||
"org_admins_can_create_new_teams": "Nur der Administrator Ihrer Organisation kann neue Teams erstellen",
|
"org_admins_can_create_new_teams": "Nur der Administrator Ihrer Organization kann neue Teams erstellen",
|
||||||
"google_new_spam_policy": "Die neuen Spam-Richtlinien von Google könnten verhindern, dass Sie E-Mail- und Kalenderbenachrichtigungen zu dieser Buchung erhalten.",
|
"google_new_spam_policy": "Die neuen Spam-Richtlinien von Google könnten verhindern, dass Sie E-Mail- und Kalenderbenachrichtigungen zu dieser Buchung erhalten.",
|
||||||
"resolve": "Beheben",
|
"resolve": "Beheben",
|
||||||
"no_organization_slug": "Beim Erstellen von Teams für diese Organisation ist ein Fehler aufgetreten. URL Slug fehlt.",
|
"no_organization_slug": "Beim Erstellen von Teams für diese Organization ist ein Fehler aufgetreten. URL Slug fehlt.",
|
||||||
"org_name": "Name der Organisation",
|
"org_name": "Name der Organization",
|
||||||
"org_url": "URL der Organisation",
|
"org_url": "URL der Organization",
|
||||||
"copy_link_org": "Link zur Organisation kopieren",
|
"copy_link_org": "Link zur Organization kopieren",
|
||||||
"404_the_org": "Die Organisation",
|
"404_the_org": "Die Organization",
|
||||||
"404_the_team": "Das Team",
|
"404_the_team": "Das Team",
|
||||||
"404_claim_entity_org": "Beanspruchen Sie Ihre Subdomain für Ihre Organisation",
|
"404_claim_entity_org": "Beanspruchen Sie Ihre Subdomain für Ihre Organization",
|
||||||
"404_claim_entity_team": "Dieses Team beanspruchen und gemeinsam mit der Verwaltung von Verfügbarkeitsplänen beginnen",
|
"404_claim_entity_team": "Dieses Team beanspruchen und gemeinsam mit der Verwaltung von Verfügbarkeitsplänen beginnen",
|
||||||
"insights_all_org_filter": "Alle Apps",
|
"insights_all_org_filter": "Alle Apps",
|
||||||
"insights_team_filter": "Team: {{teamName}}",
|
"insights_team_filter": "Team: {{teamName}}",
|
||||||
@@ -1971,6 +1974,7 @@
|
|||||||
"org_team_names_example_5": "z.B. Data Analytics Team",
|
"org_team_names_example_5": "z.B. Data Analytics Team",
|
||||||
"org_max_team_warnings": "Weitere Teams können Sie zu einem späteren Zeitpunkt hinzufügen.",
|
"org_max_team_warnings": "Weitere Teams können Sie zu einem späteren Zeitpunkt hinzufügen.",
|
||||||
"what_is_this_meeting_about": "Worum geht es in diesem Termin?",
|
"what_is_this_meeting_about": "Worum geht es in diesem Termin?",
|
||||||
|
"kyc_verification_information": "Aus Sicherheitsgründen müssen Sie Ihren {{teamOrAccount}} verifizieren, bevor Sie Textnachrichten an die Teilnehmer senden können. Bitte kontaktieren Sie uns unter <a>{{supportEmail}}</a> und geben Sie folgende Informationen an:",
|
||||||
"org_admin_other_teams": "Weitere Teams",
|
"org_admin_other_teams": "Weitere Teams",
|
||||||
"no_other_teams_found": "Keine weiteren Teams gefunden",
|
"no_other_teams_found": "Keine weiteren Teams gefunden",
|
||||||
"no_other_teams_found_description": "Es gibt keine weiteren Teams in dieser Organisation.",
|
"no_other_teams_found_description": "Es gibt keine weiteren Teams in dieser Organisation.",
|
||||||
|
|||||||
@@ -256,6 +256,8 @@
|
|||||||
"available_apps": "Available Apps",
|
"available_apps": "Available Apps",
|
||||||
"available_apps_lower_case": "Available apps",
|
"available_apps_lower_case": "Available apps",
|
||||||
"available_apps_desc": "You have no apps installed. View popular apps below and explore more in our <1>App Store</1>",
|
"available_apps_desc": "You have no apps installed. View popular apps below and explore more in our <1>App Store</1>",
|
||||||
|
"fixed_host_helper": "Add anyone who needs to attend the event. <1>Learn more</1>",
|
||||||
|
"round_robin_helper":"People in the group take turns and only one person will show up for the event.",
|
||||||
"check_email_reset_password": "Check your email. We sent you a link to reset your password.",
|
"check_email_reset_password": "Check your email. We sent you a link to reset your password.",
|
||||||
"finish": "Finish",
|
"finish": "Finish",
|
||||||
"organization_general_description": "Manage settings for your team language and timezone",
|
"organization_general_description": "Manage settings for your team language and timezone",
|
||||||
@@ -405,6 +407,8 @@
|
|||||||
"allow_dynamic_booking_tooltip": "Group booking links that can be created dynamically by adding multiple usernames with a '+'. example: '{{appName}}/bailey+peer'",
|
"allow_dynamic_booking_tooltip": "Group booking links that can be created dynamically by adding multiple usernames with a '+'. example: '{{appName}}/bailey+peer'",
|
||||||
"allow_dynamic_booking": "Allow attendees to book you through dynamic group bookings",
|
"allow_dynamic_booking": "Allow attendees to book you through dynamic group bookings",
|
||||||
"dynamic_booking": "Dynamic group links",
|
"dynamic_booking": "Dynamic group links",
|
||||||
|
"allow_seo_indexing": "Allow search engines to access your public content",
|
||||||
|
"seo_indexing": "Allow SEO Indexing",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"email_placeholder": "jdoe@example.com",
|
"email_placeholder": "jdoe@example.com",
|
||||||
"full_name": "Full name",
|
"full_name": "Full name",
|
||||||
@@ -1261,6 +1265,7 @@
|
|||||||
"error_updating_settings": "Error updating settings",
|
"error_updating_settings": "Error updating settings",
|
||||||
"personal_cal_url": "My personal {{appName}} URL",
|
"personal_cal_url": "My personal {{appName}} URL",
|
||||||
"bio_hint": "A few sentences about yourself. this will appear on your personal url page.",
|
"bio_hint": "A few sentences about yourself. this will appear on your personal url page.",
|
||||||
|
"user_has_no_bio": "This user has not added a bio yet.",
|
||||||
"delete_account_modal_title": "Delete Account",
|
"delete_account_modal_title": "Delete Account",
|
||||||
"confirm_delete_account_modal": "Are you sure you want to delete your {{appName}} account?",
|
"confirm_delete_account_modal": "Are you sure you want to delete your {{appName}} account?",
|
||||||
"delete_my_account": "Delete my account",
|
"delete_my_account": "Delete my account",
|
||||||
@@ -1718,7 +1723,7 @@
|
|||||||
"identifier": "Identifier",
|
"identifier": "Identifier",
|
||||||
"duplicate_email": "Email is duplicate",
|
"duplicate_email": "Email is duplicate",
|
||||||
"booking_with_payment_cancelled": "Paying for this event is no longer possible",
|
"booking_with_payment_cancelled": "Paying for this event is no longer possible",
|
||||||
"booking_with_payment_cancelled_already_paid": "A refund for this booking payment it's on the way.",
|
"booking_with_payment_cancelled_already_paid": "A refund for this booking payment is on its way.",
|
||||||
"booking_with_payment_cancelled_refunded": "This booking payment has been refunded.",
|
"booking_with_payment_cancelled_refunded": "This booking payment has been refunded.",
|
||||||
"booking_confirmation_failed": "Booking confirmation failed",
|
"booking_confirmation_failed": "Booking confirmation failed",
|
||||||
"not_enough_seats": "Not enough seats",
|
"not_enough_seats": "Not enough seats",
|
||||||
@@ -1850,6 +1855,8 @@
|
|||||||
"insights_no_data_found_for_filter": "No data found for the selected filter or selected dates.",
|
"insights_no_data_found_for_filter": "No data found for the selected filter or selected dates.",
|
||||||
"acknowledge_booking_no_show_fee": "I acknowledge that if I do not attend this event that a {{amount, currency}} no show fee will be applied to my card.",
|
"acknowledge_booking_no_show_fee": "I acknowledge that if I do not attend this event that a {{amount, currency}} no show fee will be applied to my card.",
|
||||||
"card_details": "Card details",
|
"card_details": "Card details",
|
||||||
|
"something_went_wrong_on_our_end":"Something went wrong on our end. Get in touch with our support team, and we’ll get it fixed right away for you.",
|
||||||
|
"please_provide_following_text_to_suppport":"Please provide the following text when contacting support to better help you",
|
||||||
"seats_and_no_show_fee_error": "Currently cannot enable seats and charge a no-show fee",
|
"seats_and_no_show_fee_error": "Currently cannot enable seats and charge a no-show fee",
|
||||||
"complete_your_booking": "Complete your booking",
|
"complete_your_booking": "Complete your booking",
|
||||||
"complete_your_booking_subject": "Complete your booking: {{title}} on {{date}}",
|
"complete_your_booking_subject": "Complete your booking: {{title}} on {{date}}",
|
||||||
@@ -1899,6 +1906,7 @@
|
|||||||
"first_event_type_webhook_description": "Create your first webhook for this event type",
|
"first_event_type_webhook_description": "Create your first webhook for this event type",
|
||||||
"install_app_on": "Install app on",
|
"install_app_on": "Install app on",
|
||||||
"create_for": "Create for",
|
"create_for": "Create for",
|
||||||
|
"currency": "Currency",
|
||||||
"setup_organization": "Setup an Organization",
|
"setup_organization": "Setup an Organization",
|
||||||
"organization_banner_description": "Create an environments where your teams can create shared apps, workflows and event types with round-robin and collective scheduling.",
|
"organization_banner_description": "Create an environments where your teams can create shared apps, workflows and event types with round-robin and collective scheduling.",
|
||||||
"organization_banner_title": "Manage organizations with multiple teams",
|
"organization_banner_title": "Manage organizations with multiple teams",
|
||||||
@@ -1975,8 +1983,20 @@
|
|||||||
"org_team_names_example_5": "e.g. Data Analytics Team",
|
"org_team_names_example_5": "e.g. Data Analytics Team",
|
||||||
"org_max_team_warnings": "You will be able to add more teams later on.",
|
"org_max_team_warnings": "You will be able to add more teams later on.",
|
||||||
"what_is_this_meeting_about": "What is this meeting about?",
|
"what_is_this_meeting_about": "What is this meeting about?",
|
||||||
|
"add_to_team":"Add to team",
|
||||||
|
"remove_users_from_org": "Remove users from organization",
|
||||||
|
"remove_users_from_org_confirm":"Are you sure you want to remove {{userCount}} users from this organization?",
|
||||||
|
"user_has_no_schedules":"This user has not setup any schedules yet",
|
||||||
|
"user_isnt_in_any_teams":"This user is not in any teams",
|
||||||
"requires_booker_email_verification": "Requires booker email verification",
|
"requires_booker_email_verification": "Requires booker email verification",
|
||||||
"description_requires_booker_email_verification": "To ensure booker's email verification before scheduling events",
|
"description_requires_booker_email_verification": "To ensure booker's email verification before scheduling events",
|
||||||
|
"requires_confirmation_mandatory": "Text messages can only be sent to attendees when event type requires confirmation.",
|
||||||
|
"kyc_verification_information": "To ensure security, you have to verify your {{teamOrAccount}} before sending text messages to attendees. Please contact us at <a>{{supportEmail}}</a> and provide the following information:",
|
||||||
|
"kyc_verification_documents": "<ul><li>Your {{teamOrUser}}</li><li>For businesses: Attach your Business Verification Documentation</li><li>For individuals: Attach a government-issued ID</li></ul>",
|
||||||
|
"verify_team_or_account": "Verify {{teamOrAccount}}",
|
||||||
|
"verify_account": "Verify Account",
|
||||||
|
"kyc_verification": "KYC Verification",
|
||||||
|
"organizations": "Organizations",
|
||||||
"org_admin_other_teams": "Other teams",
|
"org_admin_other_teams": "Other teams",
|
||||||
"org_admin_other_teams_description": "Here you can see teams inside your organization but that you are not part of. You can add yourself to them if needed.",
|
"org_admin_other_teams_description": "Here you can see teams inside your organization but that you are not part of. You can add yourself to them if needed.",
|
||||||
"no_other_teams_found": "No other teams found",
|
"no_other_teams_found": "No other teams found",
|
||||||
@@ -1985,5 +2005,7 @@
|
|||||||
"attendee_last_name_variable": "Attendee last name",
|
"attendee_last_name_variable": "Attendee last name",
|
||||||
"attendee_first_name_info": "The person booking's first name",
|
"attendee_first_name_info": "The person booking's first name",
|
||||||
"attendee_last_name_info": "The person booking's last name",
|
"attendee_last_name_info": "The person booking's last name",
|
||||||
|
"me": "Me",
|
||||||
|
"verify_team_tooltip": "Verify your team to enable sending messages to attendees",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -225,6 +225,7 @@
|
|||||||
"create_account": "Créer un compte",
|
"create_account": "Créer un compte",
|
||||||
"confirm_password": "Confirmer le mot de passe",
|
"confirm_password": "Confirmer le mot de passe",
|
||||||
"confirm_auth_change": "Cela changera la façon dont vous vous connectez",
|
"confirm_auth_change": "Cela changera la façon dont vous vous connectez",
|
||||||
|
"confirm_auth_email_change": "La modification de l'adresse e-mail déconnectera votre méthode d'authentification actuelle pour vous connecter à Cal.com. Nous vous demanderons de vérifier votre nouvelle adresse e-mail. Ensuite, vous serez déconnecté et devrez utiliser votre nouvelle adresse e-mail pour vous connecter après avoir défini votre mot de passe en suivant les instructions qui seront envoyées à votre adresse e-mail.",
|
||||||
"reset_your_password": "Définissez votre nouveau mot de passe avec les instructions envoyées à votre adresse e-mail.",
|
"reset_your_password": "Définissez votre nouveau mot de passe avec les instructions envoyées à votre adresse e-mail.",
|
||||||
"email_change": "Reconnectez-vous avec votre nouvelle adresse e-mail et votre nouveau mot de passe.",
|
"email_change": "Reconnectez-vous avec votre nouvelle adresse e-mail et votre nouveau mot de passe.",
|
||||||
"create_your_account": "Créez votre compte",
|
"create_your_account": "Créez votre compte",
|
||||||
@@ -255,6 +256,8 @@
|
|||||||
"available_apps": "Applications disponibles",
|
"available_apps": "Applications disponibles",
|
||||||
"available_apps_lower_case": "Applications disponibles",
|
"available_apps_lower_case": "Applications disponibles",
|
||||||
"available_apps_desc": "Aucune application installée. Consultez les applications populaires ci-dessous et découvrez-en plus dans notre <1>App Store</1>.",
|
"available_apps_desc": "Aucune application installée. Consultez les applications populaires ci-dessous et découvrez-en plus dans notre <1>App Store</1>.",
|
||||||
|
"fixed_host_helper": "Ajouter toute personne qui doit assister à l'événement. <1>En savoir plus</1>",
|
||||||
|
"round_robin_helper": "Les membres du groupe se relaient et une seule personne se présentera à l'événement.",
|
||||||
"check_email_reset_password": "Vérifiez vos e-mails. Nous vous avons envoyé un lien pour réinitialiser votre mot de passe.",
|
"check_email_reset_password": "Vérifiez vos e-mails. Nous vous avons envoyé un lien pour réinitialiser votre mot de passe.",
|
||||||
"finish": "Terminer",
|
"finish": "Terminer",
|
||||||
"organization_general_description": "Gérez les paramètres de langue et de fuseau horaire de votre équipe.",
|
"organization_general_description": "Gérez les paramètres de langue et de fuseau horaire de votre équipe.",
|
||||||
@@ -1847,6 +1850,8 @@
|
|||||||
"insights_no_data_found_for_filter": "Aucune donnée trouvée pour le filtre ou les dates sélectionnés.",
|
"insights_no_data_found_for_filter": "Aucune donnée trouvée pour le filtre ou les dates sélectionnés.",
|
||||||
"acknowledge_booking_no_show_fee": "Je reconnais que si je ne participe pas à cet événement, des frais d'absence de {{amount, currency}} seront appliqués à ma carte.",
|
"acknowledge_booking_no_show_fee": "Je reconnais que si je ne participe pas à cet événement, des frais d'absence de {{amount, currency}} seront appliqués à ma carte.",
|
||||||
"card_details": "Détails de la carte",
|
"card_details": "Détails de la carte",
|
||||||
|
"something_went_wrong_on_our_end": "Quelque chose s'est mal passé de notre côté. Contactez notre équipe de support, et nous le réparerons immédiatement.",
|
||||||
|
"please_provide_following_text_to_suppport": "Veuillez fournir le texte suivant lorsque vous contactez le support pour mieux vous aider",
|
||||||
"seats_and_no_show_fee_error": "Il n'est pas possible d'activer les places et de facturer des frais d'absence pour le moment",
|
"seats_and_no_show_fee_error": "Il n'est pas possible d'activer les places et de facturer des frais d'absence pour le moment",
|
||||||
"complete_your_booking": "Terminez votre réservation",
|
"complete_your_booking": "Terminez votre réservation",
|
||||||
"complete_your_booking_subject": "Terminez votre réservation : {{title}} le {{date}}",
|
"complete_your_booking_subject": "Terminez votre réservation : {{title}} le {{date}}",
|
||||||
@@ -1896,6 +1901,7 @@
|
|||||||
"first_event_type_webhook_description": "Créez votre premier webhook pour ce type d'événement",
|
"first_event_type_webhook_description": "Créez votre premier webhook pour ce type d'événement",
|
||||||
"install_app_on": "Installer l’application sur",
|
"install_app_on": "Installer l’application sur",
|
||||||
"create_for": "Créer pour",
|
"create_for": "Créer pour",
|
||||||
|
"currency": "Devise",
|
||||||
"setup_organization": "Configurer une organisation",
|
"setup_organization": "Configurer une organisation",
|
||||||
"organization_banner_description": "Créez un environnement où vos équipes peuvent créer des applications partagées, des workflows et des types d'événements avec une planification round-robin et collective.",
|
"organization_banner_description": "Créez un environnement où vos équipes peuvent créer des applications partagées, des workflows et des types d'événements avec une planification round-robin et collective.",
|
||||||
"organization_banner_title": "Gérer les organisations avec plusieurs équipes",
|
"organization_banner_title": "Gérer les organisations avec plusieurs équipes",
|
||||||
@@ -1972,11 +1978,20 @@
|
|||||||
"org_team_names_example_5": "p. ex. Équipe d'analyse de données",
|
"org_team_names_example_5": "p. ex. Équipe d'analyse de données",
|
||||||
"org_max_team_warnings": "Vous pourrez ajouter plus d'équipes plus tard.",
|
"org_max_team_warnings": "Vous pourrez ajouter plus d'équipes plus tard.",
|
||||||
"what_is_this_meeting_about": "En quoi consiste ce rendez-vous ?",
|
"what_is_this_meeting_about": "En quoi consiste ce rendez-vous ?",
|
||||||
|
"requires_confirmation_mandatory": "Les messages ne peuvent être envoyés aux participants que lorsque le type d'événement nécessite une confirmation.",
|
||||||
|
"kyc_verification_information": "Pour garantir la sécurité, vous devez vérifier votre {{teamOrAccount}} avant d'envoyer des messages aux participants. Veuillez nous contacter à <a>{{supportEmail}}</a> et fournir les informations suivantes :",
|
||||||
|
"kyc_verification_documents": "<ul><li>Votre {{teamOrUser}}</li><li>Pour les entreprises : Joignez votre document de vérification d'entreprise</li><li>Pour les particuliers : Joignez une pièce d'identité</li></ul>",
|
||||||
|
"verify_team_or_account": "Vérifier {{teamOrAccount}}",
|
||||||
|
"verify_account": "Vérifier le compte",
|
||||||
|
"kyc_verification": "Vérification KYC",
|
||||||
|
"organizations": "Organisations",
|
||||||
"org_admin_other_teams": "Autres équipes",
|
"org_admin_other_teams": "Autres équipes",
|
||||||
"org_admin_other_teams_description": "Ici, vous pouvez voir les équipes au sein de votre organisation dont vous ne faites pas partie. Vous pouvez vous y ajouter si nécessaire.",
|
"org_admin_other_teams_description": "Ici, vous pouvez voir les équipes au sein de votre organisation dont vous ne faites pas partie. Vous pouvez vous y ajouter si nécessaire.",
|
||||||
"no_other_teams_found": "Aucune autre équipe trouvée",
|
"no_other_teams_found": "Aucune autre équipe trouvée",
|
||||||
"no_other_teams_found_description": "Il n'y a pas d'autres équipes dans cette organisation.",
|
"no_other_teams_found_description": "Il n'y a pas d'autres équipes dans cette organisation.",
|
||||||
"attendee_first_name_variable": "Prénom du participant",
|
"attendee_first_name_variable": "Prénom du participant",
|
||||||
"attendee_last_name_variable": "Nom du participant",
|
"attendee_last_name_variable": "Nom du participant",
|
||||||
|
"me": "Moi",
|
||||||
|
"verify_team_tooltip": "Vérifiez votre équipe pour activer l'envoi de messages aux participants",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Ajoutez vos nouvelles chaînes ci-dessus ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Ajoutez vos nouvelles chaînes ci-dessus ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
"team_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לצוותים. שמנו לב שהצוות שלך, \"{{teamName}}\", זקוק לשדרוג.",
|
"team_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לצוותים. שמנו לב שהצוות שלך, \"{{teamName}}\", זקוק לשדרוג.",
|
||||||
"upgrade_banner_action": "כאן משדרגים",
|
"upgrade_banner_action": "כאן משדרגים",
|
||||||
"team_upgraded_successfully": "הצוות שלך שודרג בהצלחה!",
|
"team_upgraded_successfully": "הצוות שלך שודרג בהצלחה!",
|
||||||
"org_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לארגונים. שמנו לב שהארגון שלך, \"{{teamName}}\", זקוק לשדרוג.",
|
"org_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לארגונים. שמנו לב שה-Organization שלך, \"{{teamName}}\", זקוק לשדרוג.",
|
||||||
"org_upgraded_successfully": "השדרוג של הארגון שלך בוצע בהצלחה!",
|
"org_upgraded_successfully": "השדרוג של הארגון שלך בוצע בהצלחה!",
|
||||||
"use_link_to_reset_password": "נא להשתמש בקישור הבא כדי לאפס את הסיסמה",
|
"use_link_to_reset_password": "נא להשתמש בקישור הבא כדי לאפס את הסיסמה",
|
||||||
"hey_there": "שלום,",
|
"hey_there": "שלום,",
|
||||||
@@ -551,7 +551,7 @@
|
|||||||
"team_description": "מספר משפטים אודות הצוות. המידע הזה יופיע בדף ה-URL של הצוות.",
|
"team_description": "מספר משפטים אודות הצוות. המידע הזה יופיע בדף ה-URL של הצוות.",
|
||||||
"org_description": "מספר משפטים אודות הארגון. הם יופיעו בדף עם כתובת ה-URL של הארגון.",
|
"org_description": "מספר משפטים אודות הארגון. הם יופיעו בדף עם כתובת ה-URL של הארגון.",
|
||||||
"members": "חברים",
|
"members": "חברים",
|
||||||
"organization_members": "חברי הארגון",
|
"organization_members": "חברי Organization",
|
||||||
"member": "חבר/ת",
|
"member": "חבר/ת",
|
||||||
"number_member_one": "חבר {{count}}",
|
"number_member_one": "חבר {{count}}",
|
||||||
"number_member_other": "{{count}} חברים",
|
"number_member_other": "{{count}} חברים",
|
||||||
@@ -699,7 +699,7 @@
|
|||||||
"create_team_to_get_started": "צור צוות כדי להתחיל",
|
"create_team_to_get_started": "צור צוות כדי להתחיל",
|
||||||
"teams": "צוותים",
|
"teams": "צוותים",
|
||||||
"team": "צוות",
|
"team": "צוות",
|
||||||
"organization": "ארגון",
|
"organization": "Organization",
|
||||||
"team_billing": "חיוב צוותים",
|
"team_billing": "חיוב צוותים",
|
||||||
"team_billing_description": "ניהול החיוב עבור הצוות",
|
"team_billing_description": "ניהול החיוב עבור הצוות",
|
||||||
"upgrade_to_flexible_pro_title": "שינינו את החיוב בעבור צוותים",
|
"upgrade_to_flexible_pro_title": "שינינו את החיוב בעבור צוותים",
|
||||||
@@ -1151,7 +1151,7 @@
|
|||||||
"custom": "התאמה אישית",
|
"custom": "התאמה אישית",
|
||||||
"reminder": "תזכורת",
|
"reminder": "תזכורת",
|
||||||
"rescheduled": "נקבע מועד חדש",
|
"rescheduled": "נקבע מועד חדש",
|
||||||
"completed": "הושלם",
|
"completed": "הושלמה",
|
||||||
"reminder_email": "תזכורת: {{eventType}} עם {{name}} בתאריך {{date}}",
|
"reminder_email": "תזכורת: {{eventType}} עם {{name}} בתאריך {{date}}",
|
||||||
"not_triggering_existing_bookings": "לא יופעל עבור הזמנות קיימות מאחר שהמשתמש יתבקש למסור מספר טלפון בעת הזמנת האירוע.",
|
"not_triggering_existing_bookings": "לא יופעל עבור הזמנות קיימות מאחר שהמשתמש יתבקש למסור מספר טלפון בעת הזמנת האירוע.",
|
||||||
"minute_one": "{{count}} דקה",
|
"minute_one": "{{count}} דקה",
|
||||||
@@ -1938,7 +1938,7 @@
|
|||||||
"insights_all_org_filter": "כל האפליקציות",
|
"insights_all_org_filter": "כל האפליקציות",
|
||||||
"insights_team_filter": "צוות: {{teamName}}",
|
"insights_team_filter": "צוות: {{teamName}}",
|
||||||
"insights_user_filter": "משתמש: {{userName}}",
|
"insights_user_filter": "משתמש: {{userName}}",
|
||||||
"insights_subtitle": "הצגת תובנות הזמנה מתוך האירועים שלך",
|
"insights_subtitle": "הצגת insights לגבי הזמנות מתוך האירועים שלך",
|
||||||
"custom_plan": "חבילה בהתאמה אישית",
|
"custom_plan": "חבילה בהתאמה אישית",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "Informazioni sul team",
|
"team_info": "Informazioni sul team",
|
||||||
"request_another_invitation_email": "Se preferisci non usare {{toEmail}} come email {{appName}} o già hai un account {{appName}}, per favore richiedi un altro invito a quella email.",
|
"request_another_invitation_email": "Se preferisci non usare {{toEmail}} come email {{appName}} o già hai un account {{appName}}, per favore richiedi un altro invito a quella email.",
|
||||||
"you_have_been_invited": "Sei stato invitato ad unirti al team {{teamName}}",
|
"you_have_been_invited": "Sei stato invitato ad unirti al team {{teamName}}",
|
||||||
"user_invited_you": "{{user}} ti ha invitato a unirti al {{team}} {{entity}} su {{appName}}",
|
"user_invited_you": "{{user}} ti ha invitato a unirti a {{entity}} {{team}} su {{appName}}",
|
||||||
"hidden_team_member_title": "Sei nascosto in questo team",
|
"hidden_team_member_title": "Sei nascosto in questo team",
|
||||||
"hidden_team_member_message": "Il tuo posto non è pagato. Passa a Pro oppure informa il proprietario del team che può pagare il tuo posto.",
|
"hidden_team_member_message": "Il tuo posto non è pagato. Passa a Pro oppure informa il proprietario del team che può pagare il tuo posto.",
|
||||||
"hidden_team_owner_message": "Per utilizzare i team ti occorre un account Pro. Sarai nascosto finché non cambierai piano.",
|
"hidden_team_owner_message": "Per utilizzare i team ti occorre un account Pro. Sarai nascosto finché non cambierai piano.",
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
"team_upgrade_banner_description": "Grazie per aver provato il nostro piano team. Abbiamo notato che è necessario effettuare l'upgrade del tuo team \"{{teamName}}\".",
|
"team_upgrade_banner_description": "Grazie per aver provato il nostro piano team. Abbiamo notato che è necessario effettuare l'upgrade del tuo team \"{{teamName}}\".",
|
||||||
"upgrade_banner_action": "Effettua l'upgrade",
|
"upgrade_banner_action": "Effettua l'upgrade",
|
||||||
"team_upgraded_successfully": "Il tuo team è stato aggiornato!",
|
"team_upgraded_successfully": "Il tuo team è stato aggiornato!",
|
||||||
"org_upgrade_banner_description": "Grazie per aver provato il nostro piano Organization. Abbiamo notato che è necessario eseguire l'upgrade per la tua organizzazione \"{{teamName}}\".",
|
"org_upgrade_banner_description": "Grazie per aver provato il nostro piano Organization. Abbiamo notato che è necessario eseguire l'upgrade del piano Organization per \"{{teamName}}\".",
|
||||||
"org_upgraded_successfully": "È stato eseguito l'upgrade della tua organizzazione!",
|
"org_upgraded_successfully": "È stato eseguito l'upgrade del piano Organization!",
|
||||||
"use_link_to_reset_password": "Usa il link qui sotto per reimpostare la tua password",
|
"use_link_to_reset_password": "Usa il link qui sotto per reimpostare la tua password",
|
||||||
"hey_there": "Ciao,",
|
"hey_there": "Ciao,",
|
||||||
"forgot_your_password_calcom": "Hai dimenticato la password? - {{appName}}",
|
"forgot_your_password_calcom": "Hai dimenticato la password? - {{appName}}",
|
||||||
@@ -555,7 +555,7 @@
|
|||||||
"member": "Membri",
|
"member": "Membri",
|
||||||
"number_member_one": "{{count}} membro",
|
"number_member_one": "{{count}} membro",
|
||||||
"number_member_other": "{{count}} membri",
|
"number_member_other": "{{count}} membri",
|
||||||
"number_selected": "{{count}} selezionati",
|
"number_selected": "{{count}} selezionato/i",
|
||||||
"owner": "Proprietario",
|
"owner": "Proprietario",
|
||||||
"admin": "Amministratore",
|
"admin": "Amministratore",
|
||||||
"administrator_user": "Utente amministratore",
|
"administrator_user": "Utente amministratore",
|
||||||
@@ -1912,7 +1912,7 @@
|
|||||||
"organization_admin_invited_body": "Unisciti al tuo team su {{orgName}} per concentrarti sulle riunioni, non sulla loro pianificazione!",
|
"organization_admin_invited_body": "Unisciti al tuo team su {{orgName}} per concentrarti sulle riunioni, non sulla loro pianificazione!",
|
||||||
"duplicated_slugs_warning": "Non è stato possibile creare i seguenti team a causa di slug duplicati: {{slugs}}",
|
"duplicated_slugs_warning": "Non è stato possibile creare i seguenti team a causa di slug duplicati: {{slugs}}",
|
||||||
"team_names_empty": "I nomi di team non possono essere vuoti",
|
"team_names_empty": "I nomi di team non possono essere vuoti",
|
||||||
"team_names_repeated": "I nomi di team non possono essere ripetuti",
|
"team_names_repeated": "I nomi di team devono essere unici",
|
||||||
"user_belongs_organization": "L'utente appartiene a un'organizzazione",
|
"user_belongs_organization": "L'utente appartiene a un'organizzazione",
|
||||||
"org_no_teams_yet": "Questa organizzazione non ha ancora nessun team",
|
"org_no_teams_yet": "Questa organizzazione non ha ancora nessun team",
|
||||||
"org_no_teams_yet_description": "Se sei un amministratore, assicurati di creare dei team da mostrare qui.",
|
"org_no_teams_yet_description": "Se sei un amministratore, assicurati di creare dei team da mostrare qui.",
|
||||||
@@ -1934,7 +1934,7 @@
|
|||||||
"404_the_org": "L'organizzazione",
|
"404_the_org": "L'organizzazione",
|
||||||
"404_the_team": "Il team",
|
"404_the_team": "Il team",
|
||||||
"404_claim_entity_org": "Richiedi il sottodominio per la tua organizzazione",
|
"404_claim_entity_org": "Richiedi il sottodominio per la tua organizzazione",
|
||||||
"404_claim_entity_team": "Richiedi questo team e inizia a gestire le pianificazioni collettivamente",
|
"404_claim_entity_team": "Richiedi l'accesso a questo team per iniziare a gestire le pianificazioni collettivamente",
|
||||||
"insights_all_org_filter": "Tutte le app",
|
"insights_all_org_filter": "Tutte le app",
|
||||||
"insights_team_filter": "Team: {{teamName}}",
|
"insights_team_filter": "Team: {{teamName}}",
|
||||||
"insights_user_filter": "Utente: {{userName}}",
|
"insights_user_filter": "Utente: {{userName}}",
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
"reset_password_subject": "{{appName}}: パスワードのリセット手順",
|
"reset_password_subject": "{{appName}}: パスワードのリセット手順",
|
||||||
"verify_email_subject": "{{appName}}:アカウントを確認",
|
"verify_email_subject": "{{appName}}:アカウントを確認",
|
||||||
"check_your_email": "メールを確認してください",
|
"check_your_email": "メールを確認してください",
|
||||||
"verify_email_page_body": "{{email}} にメールを送信しました。{{appName}} からのメール配信とカレンダーが確実に連携するようにするには、メールアドレスの確認が重要です。",
|
"verify_email_page_body": "{{email}} にメールを送信しました。{{appName}} からのメール配信とカレンダー通知が確実に連携するようにするには、メールアドレスの確認が重要です。",
|
||||||
"verify_email_banner_body": "メール配信とカレンダーが確実に連携するようにするには、メールアドレスを確認してください。",
|
"verify_email_banner_body": "メール配信とカレンダー通知が確実に連携するようにするには、メールアドレスを確認してください。",
|
||||||
"verify_email_email_header": "メールアドレスの確認",
|
"verify_email_email_header": "メールアドレスの確認",
|
||||||
"verify_email_email_button": "メールを確認",
|
"verify_email_email_button": "メールを確認",
|
||||||
"verify_email_email_body": "以下のボタンをクリックして、メールアドレスを確認してください。",
|
"verify_email_email_body": "以下のボタンをクリックして、メールアドレスを確認してください。",
|
||||||
@@ -1934,7 +1934,7 @@
|
|||||||
"404_the_org": "組織",
|
"404_the_org": "組織",
|
||||||
"404_the_team": "チーム",
|
"404_the_team": "チーム",
|
||||||
"404_claim_entity_org": "組織のサブドメインを取得",
|
"404_claim_entity_org": "組織のサブドメインを取得",
|
||||||
"404_claim_entity_team": "このチームを取得して、これからはスケジュールをまとめて管理しましょう",
|
"404_claim_entity_team": "このチームの一員になって、これからはスケジュールをまとめて管理しましょう",
|
||||||
"insights_all_org_filter": "すべて",
|
"insights_all_org_filter": "すべて",
|
||||||
"insights_team_filter": "チーム:{{teamName}}",
|
"insights_team_filter": "チーム:{{teamName}}",
|
||||||
"insights_user_filter": "ユーザー:{{userName}}",
|
"insights_user_filter": "ユーザー:{{userName}}",
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "Informacje o zespole",
|
"team_info": "Informacje o zespole",
|
||||||
"request_another_invitation_email": "Jeśli wolisz nie używać {{toEmail}} jako adresu e-mail {{appName}} lub masz już konto {{appName}}, poproś o inne zaproszenie na ten e-mail.",
|
"request_another_invitation_email": "Jeśli wolisz nie używać {{toEmail}} jako adresu e-mail {{appName}} lub masz już konto {{appName}}, poproś o inne zaproszenie na ten e-mail.",
|
||||||
"you_have_been_invited": "Zostałeś zaproszony do dołączenia do zespołu {{teamName}}",
|
"you_have_been_invited": "Zostałeś zaproszony do dołączenia do zespołu {{teamName}}",
|
||||||
"user_invited_you": "Użytkownik {{user}} zaprosił Cię do dołączenia do zespołu {{team}} ({{entity}}) w aplikacji {{appName}}.",
|
"user_invited_you": "Użytkownik {{user}} zaprosił Cię do dołączenia do: {{entity}} {{team}} w aplikacji {{appName}}.",
|
||||||
"hidden_team_member_title": "Jesteś ukryty w tym zespole",
|
"hidden_team_member_title": "Jesteś ukryty w tym zespole",
|
||||||
"hidden_team_member_message": "Twoje miejsce nie jest opłacone, przejdź na wersję Pro lub poinformuj właściciela zespołu o tym, że może zapłacić za Twoje miejsce.",
|
"hidden_team_member_message": "Twoje miejsce nie jest opłacone, przejdź na wersję Pro lub poinformuj właściciela zespołu o tym, że może zapłacić za Twoje miejsce.",
|
||||||
"hidden_team_owner_message": "Potrzebujesz konta pro aby korzystać z zespołów, jesteś ukryty do czasu ulepszenia.",
|
"hidden_team_owner_message": "Potrzebujesz konta pro aby korzystać z zespołów, jesteś ukryty do czasu ulepszenia.",
|
||||||
@@ -1661,7 +1661,7 @@
|
|||||||
"email_user_cta": "Wyświetl zaproszenie",
|
"email_user_cta": "Wyświetl zaproszenie",
|
||||||
"email_no_user_invite_heading": "Zaproszono Cię do dołączenia do aplikacji {{appName}} ({{entity}})",
|
"email_no_user_invite_heading": "Zaproszono Cię do dołączenia do aplikacji {{appName}} ({{entity}})",
|
||||||
"email_no_user_invite_subheading": "Użytkownik {{invitedBy}} zaprasza Cię do dołączenia do jego zespołu w aplikacji {{appName}}. Aplikacja {{appName}} to terminarz do planowania wydarzeń, który umożliwi Tobie i Twojemu zespołowi planowanie spotkań bez czasochłonnej wymiany wiadomości e-mail.",
|
"email_no_user_invite_subheading": "Użytkownik {{invitedBy}} zaprasza Cię do dołączenia do jego zespołu w aplikacji {{appName}}. Aplikacja {{appName}} to terminarz do planowania wydarzeń, który umożliwi Tobie i Twojemu zespołowi planowanie spotkań bez czasochłonnej wymiany wiadomości e-mail.",
|
||||||
"email_user_invite_subheading": "Użytkownik {{invitedBy}} zaprasza Cię do dołączenia do jego zespołu „{{teamName}}” ({{entity}}) w aplikacji {{appName}}. Aplikacja {{appName}} to terminarz do planowania wydarzeń, który umożliwi {{entity}} planowanie spotkań bez czasochłonnej wymiany wiadomości e-mail.",
|
"email_user_invite_subheading": "Użytkownik {{invitedBy}} zaprasza Cię do dołączenia do: {{entity}} „{{teamName}}” w aplikacji {{appName}}. Aplikacja {{appName}} to terminarz do planowania wydarzeń, który umożliwi {{entity}} planowanie spotkań bez czasochłonnej wymiany wiadomości e-mail.",
|
||||||
"email_no_user_invite_steps_intro": "Przeprowadzimy Cię przez kilka krótkich etapów i wkrótce w ramach {{entity}} zaczniesz z przyjemnością korzystać z bezstresowego narzędzia planowania.",
|
"email_no_user_invite_steps_intro": "Przeprowadzimy Cię przez kilka krótkich etapów i wkrótce w ramach {{entity}} zaczniesz z przyjemnością korzystać z bezstresowego narzędzia planowania.",
|
||||||
"email_no_user_step_one": "Wybierz nazwę użytkownika",
|
"email_no_user_step_one": "Wybierz nazwę użytkownika",
|
||||||
"email_no_user_step_two": "Połącz swoje konto kalendarza",
|
"email_no_user_step_two": "Połącz swoje konto kalendarza",
|
||||||
|
|||||||
@@ -13,13 +13,19 @@
|
|||||||
"reset_password_subject": "{{appName}}: Instruções para redefinir sua senha",
|
"reset_password_subject": "{{appName}}: Instruções para redefinir sua senha",
|
||||||
"verify_email_subject": "{{appName}}: Verificar sua conta",
|
"verify_email_subject": "{{appName}}: Verificar sua conta",
|
||||||
"check_your_email": "Verifique seu e-mail",
|
"check_your_email": "Verifique seu e-mail",
|
||||||
"verify_email_page_body": "Enviamos um e-mail para {{email}}. É importante verificar seu endereço de e-mail para garantir o fornecimento do melhor e-mail e calendário de {{appName}}.",
|
"verify_email_page_body": "Enviamos um e-mail para {{email}}. É importante verificar seu endereço de e-mail para garantir o melhor envio de e-mail e calendário do {{appName}}.",
|
||||||
"verify_email_banner_body": "Verifique seu endereço de e-mail para garantir o fornecimento do melhor e-mail e calendário",
|
"verify_email_banner_body": "Verifique seu endereço de e-mail para garantir o fornecimento do melhor e-mail e calendário",
|
||||||
"verify_email_email_header": "Verifique seu endereço de e-mail",
|
"verify_email_email_header": "Verifique seu endereço de e-mail",
|
||||||
"verify_email_email_button": "Verificar e-mail",
|
"verify_email_email_button": "Verificar e-mail",
|
||||||
|
"copy_somewhere_safe": "Salve esta chave de API em um lugar seguro. Você não será capaz de vê-la novamente.",
|
||||||
"verify_email_email_body": "Por favor, verifique seu endereço de e-mail clicando no botão abaixo.",
|
"verify_email_email_body": "Por favor, verifique seu endereço de e-mail clicando no botão abaixo.",
|
||||||
|
"verify_email_by_code_email_body": "Por favor, verifique seu endereço de e-mail usando o código abaixo.",
|
||||||
"verify_email_email_link_text": "Aqui está o link caso você não goste de usar botões:",
|
"verify_email_email_link_text": "Aqui está o link caso você não goste de usar botões:",
|
||||||
|
"email_verification_code": "Insira o código de verificação",
|
||||||
|
"email_verification_code_placeholder": "Insira o código de verificação enviado para seu e-mail",
|
||||||
|
"incorrect_email_verification_code": "O código de verificação está incorreto.",
|
||||||
"email_sent": "E-mail enviado com sucesso",
|
"email_sent": "E-mail enviado com sucesso",
|
||||||
|
"email_not_sent": "Ocorreu um erro ao enviar o e-mail",
|
||||||
"event_declined_subject": "Recusado: {{title}} em {{date}}",
|
"event_declined_subject": "Recusado: {{title}} em {{date}}",
|
||||||
"event_cancelled_subject": "Cancelado: {{title}} em {{date}}",
|
"event_cancelled_subject": "Cancelado: {{title}} em {{date}}",
|
||||||
"event_request_declined": "Sua solicitação de reunião foi recusada",
|
"event_request_declined": "Sua solicitação de reunião foi recusada",
|
||||||
@@ -78,6 +84,7 @@
|
|||||||
"event_awaiting_approval_recurring": "Um evento recorrente aguarda a sua aprovação",
|
"event_awaiting_approval_recurring": "Um evento recorrente aguarda a sua aprovação",
|
||||||
"someone_requested_an_event": "Alguém solicitou o agendamento de um evento em sua agenda.",
|
"someone_requested_an_event": "Alguém solicitou o agendamento de um evento em sua agenda.",
|
||||||
"someone_requested_password_reset": "Alguém solicitou um link para alterar sua senha.",
|
"someone_requested_password_reset": "Alguém solicitou um link para alterar sua senha.",
|
||||||
|
"password_reset_email_sent": "Se estee-mail existir em nosso sistema, você receberá um e-mail de redefinição.",
|
||||||
"password_reset_instructions": "Se você não fez essa solicitação, você pode ignorar este e-mail e sua senha não será alterada.",
|
"password_reset_instructions": "Se você não fez essa solicitação, você pode ignorar este e-mail e sua senha não será alterada.",
|
||||||
"event_awaiting_approval_subject": "Aguardando aprovação: {{title}} em {{date}}",
|
"event_awaiting_approval_subject": "Aguardando aprovação: {{title}} em {{date}}",
|
||||||
"event_still_awaiting_approval": "Um evento está aguardando a sua aprovação",
|
"event_still_awaiting_approval": "Um evento está aguardando a sua aprovação",
|
||||||
@@ -217,6 +224,9 @@
|
|||||||
"already_have_an_account": "Já tem uma conta?",
|
"already_have_an_account": "Já tem uma conta?",
|
||||||
"create_account": "Criar Conta",
|
"create_account": "Criar Conta",
|
||||||
"confirm_password": "Confirmar senha",
|
"confirm_password": "Confirmar senha",
|
||||||
|
"confirm_auth_change": "Isso alterará a forma como você faz login",
|
||||||
|
"reset_your_password": "Defina sua nova senha com as instruções enviadas para seu endereço de e-mail.",
|
||||||
|
"email_change": "Volte a entrar com seu novo endereço de e-mail e senha.",
|
||||||
"create_your_account": "Criar sua conta",
|
"create_your_account": "Criar sua conta",
|
||||||
"sign_up": "Cadastro",
|
"sign_up": "Cadastro",
|
||||||
"youve_been_logged_out": "A sessão foi encerrada",
|
"youve_been_logged_out": "A sessão foi encerrada",
|
||||||
@@ -243,6 +253,9 @@
|
|||||||
"all": "Todos os apps",
|
"all": "Todos os apps",
|
||||||
"yours": "Sua conta",
|
"yours": "Sua conta",
|
||||||
"available_apps": "Aplicativos disponíveis",
|
"available_apps": "Aplicativos disponíveis",
|
||||||
|
"available_apps_lower_case": "Aplicativos disponíveis",
|
||||||
|
"available_apps_desc": "Você não tem nenhum aplicativo instalado. Veja apps populares abaixo e explore mais em nossa <1>App Store</1>",
|
||||||
|
"fixed_host_helper": "Adicione qualquer pessoa que precise participar do evento. <1>Saiba mais</1>",
|
||||||
"check_email_reset_password": "Verifique o seu email. Enviamos um link para redefinir a sua senha.",
|
"check_email_reset_password": "Verifique o seu email. Enviamos um link para redefinir a sua senha.",
|
||||||
"finish": "Finalizar",
|
"finish": "Finalizar",
|
||||||
"organization_general_description": "Gerencie as configurações para o idioma e o fuso horário da sua equipe",
|
"organization_general_description": "Gerencie as configurações para o idioma e o fuso horário da sua equipe",
|
||||||
@@ -406,6 +419,7 @@
|
|||||||
"booking_requested": "Reserva solicitada",
|
"booking_requested": "Reserva solicitada",
|
||||||
"meeting_ended": "Reunião encerrada",
|
"meeting_ended": "Reunião encerrada",
|
||||||
"form_submitted": "Formulário enviado",
|
"form_submitted": "Formulário enviado",
|
||||||
|
"booking_paid": "Reserva paga",
|
||||||
"event_triggers": "Gatilhos de eventos",
|
"event_triggers": "Gatilhos de eventos",
|
||||||
"subscriber_url": "URL do assinante",
|
"subscriber_url": "URL do assinante",
|
||||||
"create_new_webhook": "Criar um novo webhook",
|
"create_new_webhook": "Criar um novo webhook",
|
||||||
@@ -506,6 +520,7 @@
|
|||||||
"your_name": "Seu nome",
|
"your_name": "Seu nome",
|
||||||
"your_full_name": "Seu nome completo",
|
"your_full_name": "Seu nome completo",
|
||||||
"no_name": "Sem nome",
|
"no_name": "Sem nome",
|
||||||
|
"enter_number_between_range": "Por favor, insira um número entre 1 e {{maxOccurences}}",
|
||||||
"email_address": "Endereço de e-mail",
|
"email_address": "Endereço de e-mail",
|
||||||
"enter_valid_email": "Insira um e-mail válido",
|
"enter_valid_email": "Insira um e-mail válido",
|
||||||
"location": "Local",
|
"location": "Local",
|
||||||
@@ -842,6 +857,7 @@
|
|||||||
"team_view_user_availability_disabled": "O usuário precisa aceitar o convite para ver a disponibilidade",
|
"team_view_user_availability_disabled": "O usuário precisa aceitar o convite para ver a disponibilidade",
|
||||||
"set_as_away": "Definir-se como indisponível",
|
"set_as_away": "Definir-se como indisponível",
|
||||||
"set_as_free": "Desativar status indisponível",
|
"set_as_free": "Desativar status indisponível",
|
||||||
|
"toggle_away_error": "Erro ao atualizar status de ausência",
|
||||||
"user_away": "Este usuário está indisponível no momento.",
|
"user_away": "Este usuário está indisponível no momento.",
|
||||||
"user_away_description": "A pessoa que você está tentando realizar uma reserva está indisponível no momento e, portanto, não está aceitando novas reservas.",
|
"user_away_description": "A pessoa que você está tentando realizar uma reserva está indisponível no momento e, portanto, não está aceitando novas reservas.",
|
||||||
"meet_people_with_the_same_tokens": "Conheça pessoas com os mesmos tokens",
|
"meet_people_with_the_same_tokens": "Conheça pessoas com os mesmos tokens",
|
||||||
@@ -1865,6 +1881,9 @@
|
|||||||
"open_dialog_with_element_click": "Abra uma caixa de diálogo quando alguém clicar em um elemento.",
|
"open_dialog_with_element_click": "Abra uma caixa de diálogo quando alguém clicar em um elemento.",
|
||||||
"need_help_embedding": "Precisa de ajuda? Confira nosso guia para incorporar o Cal no Wix, Squarespace ou WordPress. Consulte as perguntas frequentes ou explore opções de incorporação avançadas.",
|
"need_help_embedding": "Precisa de ajuda? Confira nosso guia para incorporar o Cal no Wix, Squarespace ou WordPress. Consulte as perguntas frequentes ou explore opções de incorporação avançadas.",
|
||||||
"book_my_cal": "Reservar meu Cal",
|
"book_my_cal": "Reservar meu Cal",
|
||||||
|
"first_name": "Primeiro nome",
|
||||||
|
"last_name": "Sobrenome",
|
||||||
|
"first_last_name": "Primeiro nome, Sobrenome",
|
||||||
"invite_as": "Convidar como",
|
"invite_as": "Convidar como",
|
||||||
"form_updated_successfully": "Formulário atualizado com êxito.",
|
"form_updated_successfully": "Formulário atualizado com êxito.",
|
||||||
"disable_attendees_confirmation_emails": "Desative os e-mails de confirmação padrão para participantes",
|
"disable_attendees_confirmation_emails": "Desative os e-mails de confirmação padrão para participantes",
|
||||||
@@ -1878,6 +1897,7 @@
|
|||||||
"first_event_type_webhook_description": "Crie seu primeiro webhook para este tipo de evento",
|
"first_event_type_webhook_description": "Crie seu primeiro webhook para este tipo de evento",
|
||||||
"install_app_on": "Instalar aplicativo em",
|
"install_app_on": "Instalar aplicativo em",
|
||||||
"create_for": "Criar para",
|
"create_for": "Criar para",
|
||||||
|
"currency": "Moeda",
|
||||||
"setup_organization": "Definir uma Organização",
|
"setup_organization": "Definir uma Organização",
|
||||||
"organization_banner_description": "Crie um ambiente onde suas equipes podem criar tipos de evento, fluxos de trabalho e aplicativos compartilhados com agendamento coletivo e round robin.",
|
"organization_banner_description": "Crie um ambiente onde suas equipes podem criar tipos de evento, fluxos de trabalho e aplicativos compartilhados com agendamento coletivo e round robin.",
|
||||||
"organization_banner_title": "Gerenciar organizações com múltiplas equipes",
|
"organization_banner_title": "Gerenciar organizações com múltiplas equipes",
|
||||||
@@ -1940,5 +1960,18 @@
|
|||||||
"insights_user_filter": "Usuário: {{userName}}",
|
"insights_user_filter": "Usuário: {{userName}}",
|
||||||
"insights_subtitle": "Veja insights de reserva em seus eventos",
|
"insights_subtitle": "Veja insights de reserva em seus eventos",
|
||||||
"custom_plan": "Plano personalizado",
|
"custom_plan": "Plano personalizado",
|
||||||
|
"select_time": "Selecione o horário",
|
||||||
|
"select_date": "Selecione a data",
|
||||||
|
"see_all_available_times": "Veja todos os horários disponíveis",
|
||||||
|
"org_team_names_example": "ex.: Time de Marketing",
|
||||||
|
"org_team_names_example_1": "ex.: Time de Marketing",
|
||||||
|
"org_team_names_example_2": "ex: Time de Vendas",
|
||||||
|
"org_team_names_example_3": "ex: Time de Design",
|
||||||
|
"org_team_names_example_4": "ex: Time de Engenharia",
|
||||||
|
"org_team_names_example_5": "ex: Time de Análise de Dados",
|
||||||
|
"what_is_this_meeting_about": "De que se trata esta reunião?",
|
||||||
|
"requires_booker_email_verification": "Requer verificação de e-mail do reservante",
|
||||||
|
"verify_team_or_account": "Verificar {{teamOrAccount}}",
|
||||||
|
"verify_account": "Verificar Conta",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione suas novas strings aqui em cima ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione suas novas strings aqui em cima ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
"calcom_explained_new_user": "Conclua a configuração da sua conta {{appName}}! Está apenas a alguns passos de resolver todos os seus problemas com agendamentos.",
|
"calcom_explained_new_user": "Conclua a configuração da sua conta {{appName}}! Está apenas a alguns passos de resolver todos os seus problemas com agendamentos.",
|
||||||
"have_any_questions": "Tem perguntas? Estamos disponíveis para ajudar.",
|
"have_any_questions": "Tem perguntas? Estamos disponíveis para ajudar.",
|
||||||
"reset_password_subject": "{{appName}}: Instruções de redefinição da senha",
|
"reset_password_subject": "{{appName}}: Instruções de redefinição da senha",
|
||||||
"verify_email_subject": "{{appName}}: Verificar sua conta",
|
"verify_email_subject": "{{appName}}: Verifique a sua conta",
|
||||||
"check_your_email": "Confirme o seu e-mail",
|
"check_your_email": "Confirme o seu e-mail",
|
||||||
"verify_email_page_body": "Nós enviamos um e-mail para {{email}}. É importante verificar seu endereço de e-mail para garantir que você receberá as comunicações de {{appName}}.",
|
"verify_email_page_body": "Enviámos um e-mail para {{email}}. É importante verificar o seu endereço de e-mail para garantir que receberá as comunicações de {{appName}}.",
|
||||||
"verify_email_banner_body": "Confirme o seu endereço de e-mail para garantir a melhor entrega possível de correio eletrónico e de agenda",
|
"verify_email_banner_body": "Confirme o seu endereço de e-mail para garantir a melhor entrega possível de e-mail e de agenda",
|
||||||
"verify_email_email_header": "Confirme o seu endereço de e-mail",
|
"verify_email_email_header": "Confirme o seu endereço de e-mail",
|
||||||
"verify_email_email_button": "Confirmar o seu e-mail",
|
"verify_email_email_button": "Confirmar o seu e-mail",
|
||||||
"verify_email_email_body": "Confirme o seu endereço de e-mail clicando no botão abaixo.",
|
"verify_email_email_body": "Confirme o seu endereço de e-mail clicando no botão abaixo.",
|
||||||
@@ -87,9 +87,9 @@
|
|||||||
"your_meeting_has_been_booked": "A sua reunião foi reservada",
|
"your_meeting_has_been_booked": "A sua reunião foi reservada",
|
||||||
"event_type_has_been_rescheduled_on_time_date": "Seu {{title}} foi remarcado para {{date}}.",
|
"event_type_has_been_rescheduled_on_time_date": "Seu {{title}} foi remarcado para {{date}}.",
|
||||||
"event_has_been_rescheduled": "O seu evento foi reagendado.",
|
"event_has_been_rescheduled": "O seu evento foi reagendado.",
|
||||||
"request_reschedule_subtitle": "{{organizer}} cancelou a reserva e pediu para que escolhesse outro horário.",
|
"request_reschedule_subtitle": "{{organizer}} cancelou a reserva e pediu que escolhesse outro horário.",
|
||||||
"request_reschedule_title_organizer": "Solicitou um reagendamento a {{attendee}}",
|
"request_reschedule_title_organizer": "Solicitou um reagendamento a {{attendee}}",
|
||||||
"request_reschedule_subtitle_organizer": "Você cancelou a reserva e {{attendee}} deve escolher um novo horário para a reserva consigo.",
|
"request_reschedule_subtitle_organizer": "Cancelou a reserva e {{attendee}} deve escolher um novo horário para a reserva consigo.",
|
||||||
"rescheduled_event_type_subject": "Pedido de reagendamento enviado: {{eventType}} com {{name}} em {{date}}",
|
"rescheduled_event_type_subject": "Pedido de reagendamento enviado: {{eventType}} com {{name}} em {{date}}",
|
||||||
"requested_to_reschedule_subject_attendee": "Acção necessária para reagendamento: Por favor reserve uma nova hora para {{eventType}} com {{name}}",
|
"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}}",
|
"hi_user_name": "Olá {{name}}",
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
"team_upgrade_banner_description": "Obrigado por experimentar o nosso novo plano de equipa. Verificámos que a sua equipa \"{{teamName}}\" necessita de ser atualizada.",
|
"team_upgrade_banner_description": "Obrigado por experimentar o nosso novo plano de equipa. Verificámos que a sua equipa \"{{teamName}}\" necessita de ser atualizada.",
|
||||||
"upgrade_banner_action": "Atualize aqui",
|
"upgrade_banner_action": "Atualize aqui",
|
||||||
"team_upgraded_successfully": "A sua equipa foi actualizada com sucesso!",
|
"team_upgraded_successfully": "A sua equipa foi actualizada com sucesso!",
|
||||||
"org_upgrade_banner_description": "Obrigado por experimentar o nosso plano Organization. Verificámos que a sua Organização \"{{teamName}}\" necessita de ser atualizada.",
|
"org_upgrade_banner_description": "Obrigado por experimentar o nosso plano Organization. Verificámos que a sua Organização \"{{teamName}}\" precisa de ser atualizada.",
|
||||||
"org_upgraded_successfully": "A sua Organização foi atualizada com sucesso!",
|
"org_upgraded_successfully": "A sua Organização foi atualizada com sucesso!",
|
||||||
"use_link_to_reset_password": "Use a ligação abaixo para redefinir a sua senha",
|
"use_link_to_reset_password": "Use a ligação abaixo para redefinir a sua senha",
|
||||||
"hey_there": "Olá,",
|
"hey_there": "Olá,",
|
||||||
@@ -310,12 +310,12 @@
|
|||||||
"bookerlayout_user_settings_title": "Disposição da reserva",
|
"bookerlayout_user_settings_title": "Disposição da reserva",
|
||||||
"bookerlayout_user_settings_description": "Pode selecionar várias e os clientes podem alternar entre vistas. Isto pode ser sobreposto para cada evento.",
|
"bookerlayout_user_settings_description": "Pode selecionar várias e os clientes podem alternar entre vistas. Isto pode ser sobreposto para cada evento.",
|
||||||
"bookerlayout_month_view": "Mês",
|
"bookerlayout_month_view": "Mês",
|
||||||
"bookerlayout_week_view": "Semanal",
|
"bookerlayout_week_view": "Semana",
|
||||||
"bookerlayout_column_view": "Coluna",
|
"bookerlayout_column_view": "Coluna",
|
||||||
"bookerlayout_error_min_one_enabled": "Tem de estar ativa pelo menos uma disposição.",
|
"bookerlayout_error_min_one_enabled": "Tem de estar ativa pelo menos uma disposição.",
|
||||||
"bookerlayout_error_default_not_enabled": "A disposição selecionada como a vista predefinida não faz parte das disposições ativas.",
|
"bookerlayout_error_default_not_enabled": "A disposição selecionada como vista predefinida não faz parte das disposições ativas.",
|
||||||
"bookerlayout_error_unknown_layout": "A disposição que selecionou não é uma disposição válida.",
|
"bookerlayout_error_unknown_layout": "A disposição que selecionou não é uma disposição válida.",
|
||||||
"bookerlayout_override_global_settings": "Pode gerir isto para todos os seus tipos de eventos em <2>definições/ aparência</2> ou <6>sobrepor apenas para este evento</6>.",
|
"bookerlayout_override_global_settings": "Pode gerir isto para todos os seus tipos de eventos em <2>definições / aparência</2> ou <6>sobrepor apenas para este evento</6>.",
|
||||||
"unexpected_error_try_again": "Ocorreu um erro inesperado. Tente de novo.",
|
"unexpected_error_try_again": "Ocorreu um erro inesperado. Tente de novo.",
|
||||||
"sunday_time_error": "Hora inválida no domingo",
|
"sunday_time_error": "Hora inválida no domingo",
|
||||||
"monday_time_error": "Hora inválida na segunda-feira",
|
"monday_time_error": "Hora inválida na segunda-feira",
|
||||||
@@ -337,11 +337,11 @@
|
|||||||
"cancelling_event_recurring": "O evento é uma instância de um evento recorrente.",
|
"cancelling_event_recurring": "O evento é uma instância de um evento recorrente.",
|
||||||
"cancelling_all_recurring": "Estas são todas as restantes instâncias do evento recorrente.",
|
"cancelling_all_recurring": "Estas são todas as restantes instâncias do evento recorrente.",
|
||||||
"error_with_status_code_occured": "Ocorreu um erro com o código de estado {{status}}",
|
"error_with_status_code_occured": "Ocorreu um erro com o código de estado {{status}}",
|
||||||
"error_event_type_url_duplicate": "Um tipo de evento com essa URL já existe.",
|
"error_event_type_url_duplicate": "Já existe um tipo de evento com este URL.",
|
||||||
"error_event_type_unauthorized_create": "Você não tem autorização para criar esse evento",
|
"error_event_type_unauthorized_create": "Não tem autorização para criar este evento",
|
||||||
"error_event_type_unauthorized_update": "Você não tem autorização para editar esse evento",
|
"error_event_type_unauthorized_update": "Não tem autorização para editar este evento",
|
||||||
"error_workflow_unauthorized_create": "Você não tem autorização para criar esse evento",
|
"error_workflow_unauthorized_create": "Não tem autorização para criar este evento",
|
||||||
"error_schedule_unauthorized_create": "Você não tem autorização para criar essa agenda",
|
"error_schedule_unauthorized_create": "Não tem autorização para criar esta agenda",
|
||||||
"booking_already_cancelled": "Esta reserva já foi cancelada",
|
"booking_already_cancelled": "Esta reserva já foi cancelada",
|
||||||
"booking_already_accepted_rejected": "Esta reserva já foi aceite ou rejeitada",
|
"booking_already_accepted_rejected": "Esta reserva já foi aceite ou rejeitada",
|
||||||
"go_back_home": "Voltar à Página Inicial",
|
"go_back_home": "Voltar à Página Inicial",
|
||||||
@@ -357,7 +357,7 @@
|
|||||||
"upcoming_bookings": "Assim que alguém reservar uma hora, ela aparecerá aqui.",
|
"upcoming_bookings": "Assim que alguém reservar uma hora, ela aparecerá aqui.",
|
||||||
"recurring_bookings": "Assim que alguém reservar uma reunião recorrente, será mostrada aqui.",
|
"recurring_bookings": "Assim que alguém reservar uma reunião recorrente, será mostrada aqui.",
|
||||||
"past_bookings": "As suas reservas anteriores aparecerão aqui.",
|
"past_bookings": "As suas reservas anteriores aparecerão aqui.",
|
||||||
"cancelled_bookings": "Suas reservas canceladas aparecerão aqui.",
|
"cancelled_bookings": "As suas reservas canceladas vão aparecer aqui.",
|
||||||
"unconfirmed_bookings": "As suas marcações não confirmadas irão aparecer aqui.",
|
"unconfirmed_bookings": "As suas marcações não confirmadas irão aparecer aqui.",
|
||||||
"unconfirmed_bookings_tooltip": "Reservas não confirmadas",
|
"unconfirmed_bookings_tooltip": "Reservas não confirmadas",
|
||||||
"on": "em",
|
"on": "em",
|
||||||
@@ -398,12 +398,12 @@
|
|||||||
"browse_api_documentation": "Consulte a nossa documentação da API",
|
"browse_api_documentation": "Consulte a nossa documentação da API",
|
||||||
"leverage_our_api": "Tire partido da nossa API para controlo e personalização total.",
|
"leverage_our_api": "Tire partido da nossa API para controlo e personalização total.",
|
||||||
"create_webhook": "Criar Webhook",
|
"create_webhook": "Criar Webhook",
|
||||||
"booking_cancelled": "Reserva Cancelada",
|
"booking_cancelled": "Reserva cancelada",
|
||||||
"booking_rescheduled": "Reserva Reagendada",
|
"booking_rescheduled": "Reserva Reagendada",
|
||||||
"recording_ready": "Ligação de transferência da gravação pronta",
|
"recording_ready": "Ligação de transferência da gravação pronta",
|
||||||
"booking_created": "Reserva Criada",
|
"booking_created": "Reserva Criada",
|
||||||
"booking_rejected": "Reserva Rejeitada",
|
"booking_rejected": "Reserva rejeitada",
|
||||||
"booking_requested": "Reserva Rejeitada",
|
"booking_requested": "Reserva solicitada",
|
||||||
"meeting_ended": "A reunião terminou",
|
"meeting_ended": "A reunião terminou",
|
||||||
"form_submitted": "Formulário enviado",
|
"form_submitted": "Formulário enviado",
|
||||||
"event_triggers": "Causadores de eventos",
|
"event_triggers": "Causadores de eventos",
|
||||||
@@ -587,7 +587,7 @@
|
|||||||
"disband_team": "Dissolver Equipa",
|
"disband_team": "Dissolver Equipa",
|
||||||
"disband_team_confirmation_message": "De certeza que quer desmantelar esta equipa? Qualquer pessoa com quem tenha partilhado esta ligação de equipa deixará de poder fazer reservas através da respectiva ligação.",
|
"disband_team_confirmation_message": "De certeza que quer desmantelar esta equipa? Qualquer pessoa com quem tenha partilhado esta ligação de equipa deixará de poder fazer reservas através da respectiva ligação.",
|
||||||
"disband_org": "Dissolver Organização",
|
"disband_org": "Dissolver Organização",
|
||||||
"disband_org_confirmation_message": "Tem a certeza que deseja dissolver esta Organização? Todas as equipas e membros serão eliminados.",
|
"disband_org_confirmation_message": "Tem a certeza que quer dissolver esta organização? Todas as equipas e membros serão eliminados.",
|
||||||
"remove_member_confirmation_message": "Tem a certeza de que deseja remover este membro da equipa?",
|
"remove_member_confirmation_message": "Tem a certeza de que deseja remover este membro da equipa?",
|
||||||
"confirm_disband_team": "Sim, dissolver equipa",
|
"confirm_disband_team": "Sim, dissolver equipa",
|
||||||
"confirm_remove_member": "Sim, remover membro",
|
"confirm_remove_member": "Sim, remover membro",
|
||||||
@@ -874,16 +874,16 @@
|
|||||||
"no_category_apps_description_other": "Adicione qualquer outro tipo de aplicações para fazer todos os tipos de coisas",
|
"no_category_apps_description_other": "Adicione qualquer outro tipo de aplicações para fazer todos os tipos de coisas",
|
||||||
"no_category_apps_description_web3": "Adicione uma aplicação web3 às suas páginas de reservas",
|
"no_category_apps_description_web3": "Adicione uma aplicação web3 às suas páginas de reservas",
|
||||||
"no_category_apps_description_messaging": "Adicione uma aplicação de mensagens para configurar notificações e lembretes personalizados",
|
"no_category_apps_description_messaging": "Adicione uma aplicação de mensagens para configurar notificações e lembretes personalizados",
|
||||||
"no_category_apps_description_crm": "Adicione um aplicativo CRM para manter o controle de com quem você encontrou",
|
"no_category_apps_description_crm": "Adicione uma aplicação de CRM para manter um registo das pessoas com quem se reuniu",
|
||||||
"installed_app_calendar_description": "Defina o(s) calendário(s) para verificar se existem conflitos e assim evitar marcações sobrepostas.",
|
"installed_app_calendar_description": "Defina o(s) calendário(s) para verificar se existem conflitos e assim evitar marcações sobrepostas.",
|
||||||
"installed_app_payment_description": "Configure os serviços de processamento de pagamentos que serão utilizados nas cobranças aos seus clientes.",
|
"installed_app_payment_description": "Configure os serviços de processamento de pagamentos que serão utilizados nas cobranças aos seus clientes.",
|
||||||
"installed_app_analytics_description": "Configurar as aplicações de análise a utilizar nas suas páginas de reservas",
|
"installed_app_analytics_description": "Configurar as aplicações de análise a utilizar nas suas páginas de reservas",
|
||||||
"installed_app_other_description": "Todas as aplicações instaladas de outras categorias.",
|
"installed_app_other_description": "Todas as aplicações instaladas de outras categorias.",
|
||||||
"installed_app_conferencing_description": "Configure que aplicativos de conferência utilizar",
|
"installed_app_conferencing_description": "Configurar as aplicações de conferência a utilizar",
|
||||||
"installed_app_automation_description": "Configurar as aplicações de automatização a utilizar",
|
"installed_app_automation_description": "Configurar as aplicações de automatização a utilizar",
|
||||||
"installed_app_web3_description": "Configure as aplicações web3 a utilizar nas suas páginas de reservas",
|
"installed_app_web3_description": "Configure as aplicações web3 a utilizar nas suas páginas de reservas",
|
||||||
"installed_app_messaging_description": "Configure que aplicativos de mensagens utilizar para configurar notificações e lembretes personalizados",
|
"installed_app_messaging_description": "Configurar as aplicações de mensagens a utilizar para definir notificações e lembretes personalizados",
|
||||||
"installed_app_crm_description": "Configure que aplicativos de CRM utilizar para manter o controle de com quem você encontrou",
|
"installed_app_crm_description": "Configurar as aplicações de CRM a utilizar para manter um registo das pessoas com quem se reuniu",
|
||||||
"analytics": "Estatísticas",
|
"analytics": "Estatísticas",
|
||||||
"empty_installed_apps_headline": "Nenhuma aplicação instalada",
|
"empty_installed_apps_headline": "Nenhuma aplicação instalada",
|
||||||
"empty_installed_apps_description": "As aplicações permitem-lhe melhorar o seu fluxo de trabalho e os seus agendamentos, significativamente.",
|
"empty_installed_apps_description": "As aplicações permitem-lhe melhorar o seu fluxo de trabalho e os seus agendamentos, significativamente.",
|
||||||
@@ -909,7 +909,7 @@
|
|||||||
"create_events_on": "Criar eventos em:",
|
"create_events_on": "Criar eventos em:",
|
||||||
"enterprise_license": "Esta é uma funcionalidade empresarial",
|
"enterprise_license": "Esta é uma funcionalidade empresarial",
|
||||||
"enterprise_license_description": "Para ativar esta funcionalidade, obtenha uma chave de instalação na consola {{consoleUrl}} e adicione-a ao seu .env como CALCOM_LICENSE_KEY. Se a sua equipa já tem uma licença, entre em contacto com {{supportMail}} para obter ajuda.",
|
"enterprise_license_description": "Para ativar esta funcionalidade, obtenha uma chave de instalação na consola {{consoleUrl}} e adicione-a ao seu .env como CALCOM_LICENSE_KEY. Se a sua equipa já tem uma licença, entre em contacto com {{supportMail}} para obter ajuda.",
|
||||||
"enterprise_license_development": "Pode testar este recurso no modo de desenvolvimento. Para utilização em produção, um administrador deverá aceder a <2>/auth/setup</2> para inserir a chave da licença.",
|
"enterprise_license_development": "Pode testar esta funcionalidade no modo de desenvolvimento. Para utilização em produção, um administrador deverá aceder a <2>/auth/setup</2> para inserir a chave da licença.",
|
||||||
"missing_license": "Licença em falta",
|
"missing_license": "Licença em falta",
|
||||||
"signup_requires": "Necessita de licença comercial",
|
"signup_requires": "Necessita de licença comercial",
|
||||||
"signup_requires_description": "De momento a {{companyName}} não oferece uma versão gratuita de código aberto da página de registo. Para aceder completamente aos componentes de registo tem de adquirir uma licença comercial. Para uso pessoal, recomendamos a Prisma Data Platform ou qualquer outra interface Postgres para criar contas.",
|
"signup_requires_description": "De momento a {{companyName}} não oferece uma versão gratuita de código aberto da página de registo. Para aceder completamente aos componentes de registo tem de adquirir uma licença comercial. Para uso pessoal, recomendamos a Prisma Data Platform ou qualquer outra interface Postgres para criar contas.",
|
||||||
@@ -1072,7 +1072,7 @@
|
|||||||
"event_location": "Localização do evento",
|
"event_location": "Localização do evento",
|
||||||
"reschedule_optional": "Razão do reagendamento (opcional)",
|
"reschedule_optional": "Razão do reagendamento (opcional)",
|
||||||
"reschedule_placeholder": "Informe os restantes para que saibam porque precisa de reagendar",
|
"reschedule_placeholder": "Informe os restantes para que saibam porque precisa de reagendar",
|
||||||
"event_cancelled": "Esse evento foi cancelado",
|
"event_cancelled": "Este evento foi cancelado",
|
||||||
"emailed_information_about_cancelled_event": "Enviámos um email com o aviso para si e para os restantes participantes.",
|
"emailed_information_about_cancelled_event": "Enviámos um email com o aviso para si e para os restantes participantes.",
|
||||||
"this_input_will_shown_booking_this_event": "Este campo será mostrado na reserva deste evento",
|
"this_input_will_shown_booking_this_event": "Este campo será mostrado na reserva deste evento",
|
||||||
"meeting_url_in_conformation_email": "O URL da reunião está no email de confirmação",
|
"meeting_url_in_conformation_email": "O URL da reunião está no email de confirmação",
|
||||||
@@ -1292,7 +1292,7 @@
|
|||||||
"conferencing_description": "Adicione as suas aplicações de videoconferência para reuniões",
|
"conferencing_description": "Adicione as suas aplicações de videoconferência para reuniões",
|
||||||
"add_conferencing_app": "Adicionar aplicação de conferência",
|
"add_conferencing_app": "Adicionar aplicação de conferência",
|
||||||
"password_description": "Faça a gestão das definições para as palavras-passe da sua conta",
|
"password_description": "Faça a gestão das definições para as palavras-passe da sua conta",
|
||||||
"set_up_two_factor_authentication": "Configure sua autenticação em duas etapas",
|
"set_up_two_factor_authentication": "Configurar a autenticação de dois fatores",
|
||||||
"we_just_need_basic_info": "Precisamos apenas de algumas informações básicas para configurar o seu perfil.",
|
"we_just_need_basic_info": "Precisamos apenas de algumas informações básicas para configurar o seu perfil.",
|
||||||
"skip": "Ignorar",
|
"skip": "Ignorar",
|
||||||
"do_this_later": "Fazer isto mais tarde",
|
"do_this_later": "Fazer isto mais tarde",
|
||||||
@@ -1306,8 +1306,8 @@
|
|||||||
"connect_analytics_apps": "Associar aplicações de estatística",
|
"connect_analytics_apps": "Associar aplicações de estatística",
|
||||||
"connect_other_apps": "Associe outras aplicações",
|
"connect_other_apps": "Associe outras aplicações",
|
||||||
"connect_web3_apps": "Associe aplicações web3",
|
"connect_web3_apps": "Associe aplicações web3",
|
||||||
"connect_messaging_apps": "Conecte aplicações de mensagens",
|
"connect_messaging_apps": "Ligar aplicações de mensagens",
|
||||||
"connect_crm_apps": "Conecte aplicações de CRM",
|
"connect_crm_apps": "Ligar aplicações CRM",
|
||||||
"current_step_of_total": "Passo {{currentStep}} de {{maxSteps}}",
|
"current_step_of_total": "Passo {{currentStep}} de {{maxSteps}}",
|
||||||
"add_variable": "Adicionar variável",
|
"add_variable": "Adicionar variável",
|
||||||
"custom_phone_number": "Número do telefone personalizado",
|
"custom_phone_number": "Número do telefone personalizado",
|
||||||
@@ -1320,14 +1320,14 @@
|
|||||||
"location_info": "O local do evento",
|
"location_info": "O local do evento",
|
||||||
"additional_notes_info": "As notas adicionais da reserva",
|
"additional_notes_info": "As notas adicionais da reserva",
|
||||||
"attendee_name_info": "O nome do responsável pela reserva",
|
"attendee_name_info": "O nome do responsável pela reserva",
|
||||||
"organizer_name_info": "Nome do(a) organizador(a)",
|
"organizer_name_info": "Nome do organizador",
|
||||||
"to": "Para",
|
"to": "Para",
|
||||||
"workflow_turned_on_successfully": "Fluxo de trabalho {{workflowName}} {{offOn}} com sucesso",
|
"workflow_turned_on_successfully": "Fluxo de trabalho {{workflowName}} {{offOn}} com sucesso",
|
||||||
"download_responses": "Descarregar respostas",
|
"download_responses": "Descarregar respostas",
|
||||||
"download_responses_description": "Descarregue todas as respostas ao seu formulário em formato CSV.",
|
"download_responses_description": "Descarregue todas as respostas ao seu formulário em formato CSV.",
|
||||||
"download": "Descarregar",
|
"download": "Descarregar",
|
||||||
"download_recording": "Transferir gravação",
|
"download_recording": "Transferir gravação",
|
||||||
"recording_from_your_recent_call": "A gravação da sua chamada recente em {{appName}} está pronta para download",
|
"recording_from_your_recent_call": "A gravação da sua chamada recente em {{appName}} está pronta para descarregar",
|
||||||
"create_your_first_form": "Crie o seu primeiro formulário",
|
"create_your_first_form": "Crie o seu primeiro formulário",
|
||||||
"create_your_first_form_description": "Com os Formulários de encaminhamento, pode fazer questões qualitativas e encaminhar para a pessoa ou o tipo de evento correto.",
|
"create_your_first_form_description": "Com os Formulários de encaminhamento, pode fazer questões qualitativas e encaminhar para a pessoa ou o tipo de evento correto.",
|
||||||
"create_your_first_webhook": "Crie o seu primeiro Webhook",
|
"create_your_first_webhook": "Crie o seu primeiro Webhook",
|
||||||
@@ -1336,9 +1336,9 @@
|
|||||||
"event_one": "evento",
|
"event_one": "evento",
|
||||||
"event_other": "eventos",
|
"event_other": "eventos",
|
||||||
"profile_team_description": "Faça a gestão das definições do seu perfil de equipa",
|
"profile_team_description": "Faça a gestão das definições do seu perfil de equipa",
|
||||||
"profile_org_description": "Gerencie as configurações do perfil da sua organização",
|
"profile_org_description": "Gerir definições para o perfil da sua organização",
|
||||||
"members_team_description": "Utilizadores que estão no grupo",
|
"members_team_description": "Utilizadores que estão no grupo",
|
||||||
"organization_description": "Gerencie os membros e administradores da sua organização",
|
"organization_description": "Gerir os administradores e membros da sua organização",
|
||||||
"team_url": "Endereço da equipa",
|
"team_url": "Endereço da equipa",
|
||||||
"team_members": "Membros da equipa",
|
"team_members": "Membros da equipa",
|
||||||
"more": "Mais",
|
"more": "Mais",
|
||||||
@@ -1519,8 +1519,8 @@
|
|||||||
"find_the_best_person": "Encontre a melhor pessoa disponível e faça um ciclo pela sua equipa.",
|
"find_the_best_person": "Encontre a melhor pessoa disponível e faça um ciclo pela sua equipa.",
|
||||||
"fixed_round_robin": "Distribuição equilibrada fixa",
|
"fixed_round_robin": "Distribuição equilibrada fixa",
|
||||||
"add_one_fixed_attendee": "Adicione um participante fixo e distribua de forma equilibrada a partir de um número de participantes.",
|
"add_one_fixed_attendee": "Adicione um participante fixo e distribua de forma equilibrada a partir de um número de participantes.",
|
||||||
"calcom_is_better_with_team": "{{appName}} é melhor com times",
|
"calcom_is_better_with_team": "{{appName}} é melhor com equipas",
|
||||||
"the_calcom_team": "A equipe {{companyName}}",
|
"the_calcom_team": "A equipa {{companyName}}",
|
||||||
"add_your_team_members": "Adicione os membros da sua equipa aos seus tipos de eventos. Utilize o agendamento coletivo para incluir todos os membros ou encontre a pessoa mais adequada com o agendamento baseado numa distribuição equilibrada.",
|
"add_your_team_members": "Adicione os membros da sua equipa aos seus tipos de eventos. Utilize o agendamento coletivo para incluir todos os membros ou encontre a pessoa mais adequada com o agendamento baseado numa distribuição equilibrada.",
|
||||||
"booking_limit_reached": "O limite de reservas para este tipo de evento foi atingido",
|
"booking_limit_reached": "O limite de reservas para este tipo de evento foi atingido",
|
||||||
"duration_limit_reached": "O limite de duração para este tipo de evento foi atingido",
|
"duration_limit_reached": "O limite de duração para este tipo de evento foi atingido",
|
||||||
@@ -1539,7 +1539,7 @@
|
|||||||
"navigate_installed_apps": "Ir para as aplicações instaladas",
|
"navigate_installed_apps": "Ir para as aplicações instaladas",
|
||||||
"disabled_calendar": "Se tiver outro calendário instalado, as novas reservas serão adicionadas ao mesmo. Se não for o caso, deve associar um novo calendário para garantir que não perde novas reservas.",
|
"disabled_calendar": "Se tiver outro calendário instalado, as novas reservas serão adicionadas ao mesmo. Se não for o caso, deve associar um novo calendário para garantir que não perde novas reservas.",
|
||||||
"enable_apps": "Ativar aplicações",
|
"enable_apps": "Ativar aplicações",
|
||||||
"enable_apps_description": "Ative aplicativos que usuários podem integrar com {{appName}}",
|
"enable_apps_description": "Ativar aplicações que os utilizadores podem integrar com {{appName}}",
|
||||||
"purchase_license": "Adquira uma Licença",
|
"purchase_license": "Adquira uma Licença",
|
||||||
"already_have_key": "Eu já tenho uma chave:",
|
"already_have_key": "Eu já tenho uma chave:",
|
||||||
"already_have_key_suggestion": "Por favor, copie a sua variável de ambiente CALCOM_LICENSE_KEY existente aqui.",
|
"already_have_key_suggestion": "Por favor, copie a sua variável de ambiente CALCOM_LICENSE_KEY existente aqui.",
|
||||||
@@ -1553,9 +1553,9 @@
|
|||||||
"no_available_apps": "Não existem aplicações disponíveis",
|
"no_available_apps": "Não existem aplicações disponíveis",
|
||||||
"no_available_apps_description": "Garanta que existem aplicações na sua instalação em 'packages/app-store'",
|
"no_available_apps_description": "Garanta que existem aplicações na sua instalação em 'packages/app-store'",
|
||||||
"no_apps": "Não existem aplicações ativas nesta instância do Cal",
|
"no_apps": "Não existem aplicações ativas nesta instância do Cal",
|
||||||
"no_apps_configured": "Nenhuma aplicação foi configurada ainda",
|
"no_apps_configured": "Ainda não foi configurada nenhuma aplicação",
|
||||||
"enable_in_settings": "Você pode habilitar os aplicatovs nas configurações",
|
"enable_in_settings": "Pode ativar as aplicações nas definições",
|
||||||
"please_contact_admin": "Por favor, contate seu administrador",
|
"please_contact_admin": "Contacte o seu administrador",
|
||||||
"apps_settings": "Definições de aplicações",
|
"apps_settings": "Definições de aplicações",
|
||||||
"fill_this_field": "Por favor, preencha este campo",
|
"fill_this_field": "Por favor, preencha este campo",
|
||||||
"options": "Opções",
|
"options": "Opções",
|
||||||
@@ -1674,7 +1674,7 @@
|
|||||||
"no_workflows": "Sem fluxos de trabalho",
|
"no_workflows": "Sem fluxos de trabalho",
|
||||||
"change_filter": "Altere o filtro para ver os seus fluxos de trabalho pessoais e da equipa.",
|
"change_filter": "Altere o filtro para ver os seus fluxos de trabalho pessoais e da equipa.",
|
||||||
"change_filter_common": "Alterar o filtro para ver os resultados.",
|
"change_filter_common": "Alterar o filtro para ver os resultados.",
|
||||||
"no_results_for_filter": "Sem resultados para o filtro",
|
"no_results_for_filter": "Nenhum resultado para o filtro",
|
||||||
"recommended_next_steps": "Próximos passos recomendados",
|
"recommended_next_steps": "Próximos passos recomendados",
|
||||||
"create_a_managed_event": "Criar um tipo de evento gerido",
|
"create_a_managed_event": "Criar um tipo de evento gerido",
|
||||||
"meetings_are_better_with_the_right": "Os eventos são melhores com os elementos certos da equipa. Convide-os agora.",
|
"meetings_are_better_with_the_right": "Os eventos são melhores com os elementos certos da equipa. Convide-os agora.",
|
||||||
@@ -1802,7 +1802,7 @@
|
|||||||
"least_booked_members": "Membros com menos reservas",
|
"least_booked_members": "Membros com menos reservas",
|
||||||
"events_created": "Eventos criados",
|
"events_created": "Eventos criados",
|
||||||
"events_completed": "Eventos concluídos",
|
"events_completed": "Eventos concluídos",
|
||||||
"events_cancelled": "Eventos Cancelados",
|
"events_cancelled": "Eventos cancelados",
|
||||||
"events_rescheduled": "Eventos reagendados",
|
"events_rescheduled": "Eventos reagendados",
|
||||||
"from_last_period": "do último período",
|
"from_last_period": "do último período",
|
||||||
"from_to_date_period": "De: {{startDate}} A: {{endDate}}",
|
"from_to_date_period": "De: {{startDate}} A: {{endDate}}",
|
||||||
@@ -1836,9 +1836,9 @@
|
|||||||
"complete_your_booking": "Concluir a sua reserva",
|
"complete_your_booking": "Concluir a sua reserva",
|
||||||
"complete_your_booking_subject": "Concluir a sua reserva: {{title}} a {{date}}",
|
"complete_your_booking_subject": "Concluir a sua reserva: {{title}} a {{date}}",
|
||||||
"confirm_your_details": "Confirme os seus dados",
|
"confirm_your_details": "Confirme os seus dados",
|
||||||
"copy_invite_link": "Copiar link do convite",
|
"copy_invite_link": "Copiar a ligação do convite",
|
||||||
"edit_invite_link": "Editar configurações do link",
|
"edit_invite_link": "Editar definições da ligação",
|
||||||
"invite_link_copied": "Link do convite copiado",
|
"invite_link_copied": "Ligação de convite copiada",
|
||||||
"invite_link_deleted": "Ligação do convite copiada",
|
"invite_link_deleted": "Ligação do convite copiada",
|
||||||
"invite_link_updated": "Definições da ligação de convite guardadas",
|
"invite_link_updated": "Definições da ligação de convite guardadas",
|
||||||
"link_expires_after": "Ligações definidas para expirar depois...",
|
"link_expires_after": "Ligações definidas para expirar depois...",
|
||||||
@@ -1901,26 +1901,26 @@
|
|||||||
"set_a_password": "Definir uma palavra-passe",
|
"set_a_password": "Definir uma palavra-passe",
|
||||||
"set_a_password_description": "Isto irá criar uma conta de utilizador com o e-mail da sua organização e esta palavra-passe.",
|
"set_a_password_description": "Isto irá criar uma conta de utilizador com o e-mail da sua organização e esta palavra-passe.",
|
||||||
"organization_logo": "Logo da Organização",
|
"organization_logo": "Logo da Organização",
|
||||||
"organization_about_description": "Breve descrição sobre sua organização. Isso vai aparecer na página de perfil pública da sua organização.",
|
"organization_about_description": "Algumas frases sobre a sua organização. Isto aparecerá na página de perfil público da sua organização.",
|
||||||
"ill_do_this_later": "Farei isso depois",
|
"ill_do_this_later": "Faço mais tarde",
|
||||||
"verify_your_email": "Verifique seu e-mail",
|
"verify_your_email": "Verifique o seu e-mail",
|
||||||
"enter_digit_code": "Entre o código de 6 dígitos enviado para {{email}}",
|
"enter_digit_code": "Introduza o código de 6 dígitos que enviámos para {{email}}",
|
||||||
"verify_email_organization": "Verifique seu e-mail para criar uma organização",
|
"verify_email_organization": "Verifique o seu e-mail para criar uma organização",
|
||||||
"code_provided_invalid": "O código fornecido inválido, tente novamente",
|
"code_provided_invalid": "O código fornecido não é válido, tente novamente",
|
||||||
"email_already_used": "E-mail já está sendo usado",
|
"email_already_used": "O e-mail já está a ser utilizado",
|
||||||
"organization_admin_invited_heading": "Recebeu um convite para se juntar a {{orgName}}",
|
"organization_admin_invited_heading": "Recebeu um convite para se juntar a {{orgName}}",
|
||||||
"organization_admin_invited_body": "Junte-se à sua equipa em {{orgName}} e comece a concentrar-se em reunir e não em fazer reuniões!",
|
"organization_admin_invited_body": "Junte-se à sua equipa em {{orgName}} e comece a concentrar-se nas reuniões, não em fazer reuniões!",
|
||||||
"duplicated_slugs_warning": "Os seguintes times não puderam ser criados devido a slugs duplicados: {{slugs}}",
|
"duplicated_slugs_warning": "As seguintes equipas não puderam ser criadas devido à duplicação de slugs: {{slugs}}",
|
||||||
"team_names_empty": "Nomes de equipes não podem estar vazios",
|
"team_names_empty": "Os nomes das equipas não podem ficar vazios",
|
||||||
"team_names_repeated": "Nomes de equipes não podem se repetir",
|
"team_names_repeated": "Os nomes das equipas não podem ser repetidos",
|
||||||
"user_belongs_organization": "Usuário pertence a uma organização",
|
"user_belongs_organization": "O utilizador pertence a uma organização",
|
||||||
"org_no_teams_yet": "Essaorganização ainda não tem times",
|
"org_no_teams_yet": "Esta organização ainda não tem equipas",
|
||||||
"org_no_teams_yet_description": "Se é um administrador, deve criar equipas para serem apresentadas aqui.",
|
"org_no_teams_yet_description": "Se é um administrador, deve criar equipas para serem apresentadas aqui.",
|
||||||
"set_up": "Configurar",
|
"set_up": "Configurar",
|
||||||
"set_up_your_profile": "Configurar o seu perfil",
|
"set_up_your_profile": "Configurar o seu perfil",
|
||||||
"set_up_your_profile_description": "Deixe as pessoas saber quem você é dentro de {{orgName}} e quando interagem com a sua ligação pública.",
|
"set_up_your_profile_description": "Permita que as pessoas saibam quem você é em {{orgName}} e quando se envolvem com o seu link público.",
|
||||||
"my_profile": "Meu perfil",
|
"my_profile": "O meu perfil",
|
||||||
"my_settings": "Minhas configurações",
|
"my_settings": "As minhas definições",
|
||||||
"crm": "CRM",
|
"crm": "CRM",
|
||||||
"messaging": "Mensagens",
|
"messaging": "Mensagens",
|
||||||
"sender_id_info": "Nome ou número mostrado como remetente de um SMS (alguns países não permitem identificadores alfanuméricos de remetentes)",
|
"sender_id_info": "Nome ou número mostrado como remetente de um SMS (alguns países não permitem identificadores alfanuméricos de remetentes)",
|
||||||
@@ -1930,15 +1930,15 @@
|
|||||||
"no_organization_slug": "Ocorreu um erro ao criar equipas para esta organização. Falta o slug do URL.",
|
"no_organization_slug": "Ocorreu um erro ao criar equipas para esta organização. Falta o slug do URL.",
|
||||||
"org_name": "Nome da organização",
|
"org_name": "Nome da organização",
|
||||||
"org_url": "URL da Organização",
|
"org_url": "URL da Organização",
|
||||||
"copy_link_org": "Copie o link para organização",
|
"copy_link_org": "Copiar a ligação para a organização",
|
||||||
"404_the_org": "A organização",
|
"404_the_org": "A organização",
|
||||||
"404_the_team": "O time",
|
"404_the_team": "A equipa",
|
||||||
"404_claim_entity_org": "Reivindicar o seu subdomínio para a sua organização",
|
"404_claim_entity_org": "Reivindicar o seu subdomínio para a sua organização",
|
||||||
"404_claim_entity_team": "Reivindicar esta equipa e começar a gerir os horários em grupo",
|
"404_claim_entity_team": "Reivindicar esta equipa e começar a gerir os horários em grupo",
|
||||||
"insights_all_org_filter": "Todos as aplicações",
|
"insights_all_org_filter": "Todos as aplicações",
|
||||||
"insights_team_filter": "Time: {{teamName}}",
|
"insights_team_filter": "Equipa: {{teamName}}",
|
||||||
"insights_user_filter": "Usuário {{userName}}",
|
"insights_user_filter": "Utilizador: {{userName}}",
|
||||||
"insights_subtitle": "Veja as informações de reservas sobre os seus eventos",
|
"insights_subtitle": "Ver informações sobre reservas nos seus eventos",
|
||||||
"custom_plan": "Plano Personalizado",
|
"custom_plan": "Plano personalizado",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione as suas novas strings acima aqui ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "Informații echipă",
|
"team_info": "Informații echipă",
|
||||||
"request_another_invitation_email": "Dacă preferați să nu utilizați {{toEmail}} ca e-mail {{appName}} sau aveți deja un cont {{appName}}, vă rugăm să solicitați o altă invitație la acel e-mail.",
|
"request_another_invitation_email": "Dacă preferați să nu utilizați {{toEmail}} ca e-mail {{appName}} sau aveți deja un cont {{appName}}, vă rugăm să solicitați o altă invitație la acel e-mail.",
|
||||||
"you_have_been_invited": "Ați fost invitat să vă alăturați echipei {{teamName}}",
|
"you_have_been_invited": "Ați fost invitat să vă alăturați echipei {{teamName}}",
|
||||||
"user_invited_you": "{{user}} v-a invitat să vă alăturați echipei {{entity}} {{team}} pe {{appName}}",
|
"user_invited_you": "{{user}} v-a invitat să vă alăturați la {{entity}} {{team}} de pe {{appName}}",
|
||||||
"hidden_team_member_title": "Sunteți ascuns în această echipă",
|
"hidden_team_member_title": "Sunteți ascuns în această echipă",
|
||||||
"hidden_team_member_message": "Licența dvs. nu este plătită. Fie faceți upgrade la Pro, fie anunțați proprietarul echipei că vă poate plăti licența.",
|
"hidden_team_member_message": "Licența dvs. nu este plătită. Fie faceți upgrade la Pro, fie anunțați proprietarul echipei că vă poate plăti licența.",
|
||||||
"hidden_team_owner_message": "Aveți nevoie de un cont Pro pentru a utiliza echipe. Sunteți ascuns până când faceți upgrade.",
|
"hidden_team_owner_message": "Aveți nevoie de un cont Pro pentru a utiliza echipe. Sunteți ascuns până când faceți upgrade.",
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
"team_upgrade_banner_description": "Vă mulțumim că ați încercat noul nostru plan pentru echipe. Am observat că planul echipei dvs. „{{teamName}}” necesită un upgrade.",
|
"team_upgrade_banner_description": "Vă mulțumim că ați încercat noul nostru plan pentru echipe. Am observat că planul echipei dvs. „{{teamName}}” necesită un upgrade.",
|
||||||
"upgrade_banner_action": "Realizați upgrade aici",
|
"upgrade_banner_action": "Realizați upgrade aici",
|
||||||
"team_upgraded_successfully": "Echipa dvs. a fost actualizată cu succes!",
|
"team_upgraded_successfully": "Echipa dvs. a fost actualizată cu succes!",
|
||||||
"org_upgrade_banner_description": "Vă mulțumim că ați încercat planul nostru Organizație. Am observat că organizația dvs. „{{teamName}}” necesită un upgrade.",
|
"org_upgrade_banner_description": "Vă mulțumim că ați încercat planul nostru Organization. Am observat că organizația dvs. „{{teamName}}” necesită un upgrade.",
|
||||||
"org_upgraded_successfully": "Upgrade-ul la organizația dvs. a fost realizat cu succes!",
|
"org_upgraded_successfully": "Upgrade-ul pentru Organization a fost realizat cu succes!",
|
||||||
"use_link_to_reset_password": "Utilizați linkul de mai jos pentru a vă reseta parola",
|
"use_link_to_reset_password": "Utilizați linkul de mai jos pentru a vă reseta parola",
|
||||||
"hey_there": "Bună,",
|
"hey_there": "Bună,",
|
||||||
"forgot_your_password_calcom": "Ți-ai uitat parola? - {{appName}}",
|
"forgot_your_password_calcom": "Ți-ai uitat parola? - {{appName}}",
|
||||||
|
|||||||
@@ -129,7 +129,7 @@
|
|||||||
"team_upgrade_banner_description": "Спасибо, что попробовали наш новый тариф Team. Для работы с командой «{{teamName}}» необходимо изменить тариф.",
|
"team_upgrade_banner_description": "Спасибо, что попробовали наш новый тариф Team. Для работы с командой «{{teamName}}» необходимо изменить тариф.",
|
||||||
"upgrade_banner_action": "Изменить",
|
"upgrade_banner_action": "Изменить",
|
||||||
"team_upgraded_successfully": "Вы успешно перешли на новый тариф для своей команды!",
|
"team_upgraded_successfully": "Вы успешно перешли на новый тариф для своей команды!",
|
||||||
"org_upgrade_banner_description": "Спасибо, что попробовали наш новый тариф Organization. Для работы с «{{teamName}}» нужно перейти на тариф Organization.",
|
"org_upgrade_banner_description": "Спасибо, что попробовали наш новый тариф Organization. Для работы «{{teamName}}» нужно перейти на тариф Organization.",
|
||||||
"org_upgraded_successfully": "Вы успешно перешли на тариф Organization!",
|
"org_upgraded_successfully": "Вы успешно перешли на тариф Organization!",
|
||||||
"use_link_to_reset_password": "Используйте ссылку ниже, чтобы сбросить пароль",
|
"use_link_to_reset_password": "Используйте ссылку ниже, чтобы сбросить пароль",
|
||||||
"hey_there": "Привет,",
|
"hey_there": "Привет,",
|
||||||
@@ -307,15 +307,15 @@
|
|||||||
"layout": "Макет",
|
"layout": "Макет",
|
||||||
"bookerlayout_default_title": "Представление по умолчанию",
|
"bookerlayout_default_title": "Представление по умолчанию",
|
||||||
"bookerlayout_description": "Вы можете выбрать несколько представлений; пользователи, оформляющие бронирование, могут переключать представления.",
|
"bookerlayout_description": "Вы можете выбрать несколько представлений; пользователи, оформляющие бронирование, могут переключать представления.",
|
||||||
"bookerlayout_user_settings_title": "Макет забронированного события",
|
"bookerlayout_user_settings_title": "Представление забронированного события",
|
||||||
"bookerlayout_user_settings_description": "Вы можете выбрать несколько представлений; пользователи, оформляющие бронирование, могут переключать представления. Эту настройку можно переопределять для каждого события.",
|
"bookerlayout_user_settings_description": "Вы можете выбрать несколько представлений; пользователи, оформляющие бронирование, могут переключать представления. Эту настройку можно переопределять для каждого события.",
|
||||||
"bookerlayout_month_view": "Месяц",
|
"bookerlayout_month_view": "Месяц",
|
||||||
"bookerlayout_week_view": "Еженедельно",
|
"bookerlayout_week_view": "Неделя",
|
||||||
"bookerlayout_column_view": "Столбец",
|
"bookerlayout_column_view": "Столбец",
|
||||||
"bookerlayout_error_min_one_enabled": "Нужно выбрать по крайней мере один макет.",
|
"bookerlayout_error_min_one_enabled": "Нужно выбрать по крайней мере один макет.",
|
||||||
"bookerlayout_error_default_not_enabled": "Макет, который вы выбрали как представление по умолчанию, не входит в число доступных макетов.",
|
"bookerlayout_error_default_not_enabled": "Макет, который вы выбрали как представление по умолчанию, не входит в число доступных макетов.",
|
||||||
"bookerlayout_error_unknown_layout": "Вы выбрали недопустимый макет.",
|
"bookerlayout_error_unknown_layout": "Вы выбрали недопустимый макет.",
|
||||||
"bookerlayout_override_global_settings": "Эту настройку можно указать для всех типов событий в <2>настройках / оформление</2> или <6>переопределить только для этого события</6>.",
|
"bookerlayout_override_global_settings": "Эту настройку можно указать для всех типов событий в <2>настройках / оформление</2> или <6>указать только для этого события</6>.",
|
||||||
"unexpected_error_try_again": "Произошла непредвиденная ошибка. Попробуйте еще раз.",
|
"unexpected_error_try_again": "Произошла непредвиденная ошибка. Попробуйте еще раз.",
|
||||||
"sunday_time_error": "Недопустимое время в воскресенье",
|
"sunday_time_error": "Недопустимое время в воскресенье",
|
||||||
"monday_time_error": "Недопустимое время в понедельник",
|
"monday_time_error": "Недопустимое время в понедельник",
|
||||||
@@ -551,11 +551,11 @@
|
|||||||
"team_description": "Краткое описание вашей команды. Этот текст будет показываться на странице вашей команды.",
|
"team_description": "Краткое описание вашей команды. Этот текст будет показываться на странице вашей команды.",
|
||||||
"org_description": "Краткое описание вашей организации. Этот текст будет виден на странице вашей организации.",
|
"org_description": "Краткое описание вашей организации. Этот текст будет виден на странице вашей организации.",
|
||||||
"members": "Участники",
|
"members": "Участники",
|
||||||
"organization_members": "Сотрудники организации",
|
"organization_members": "Участники, подключенные к тарифному плану Organization",
|
||||||
"member": "Участник",
|
"member": "Участник",
|
||||||
"number_member_one": "Участники: {{count}}",
|
"number_member_one": "Участники: {{count}}",
|
||||||
"number_member_other": "Участники: {{count}}",
|
"number_member_other": "Участники: {{count}}",
|
||||||
"number_selected": "Выбрано: {{count}}",
|
"number_selected": "выбрано: {{count}}",
|
||||||
"owner": "Владелец",
|
"owner": "Владелец",
|
||||||
"admin": "Админ",
|
"admin": "Админ",
|
||||||
"administrator_user": "Администратор",
|
"administrator_user": "Администратор",
|
||||||
@@ -1151,7 +1151,7 @@
|
|||||||
"custom": "Пользовательский",
|
"custom": "Пользовательский",
|
||||||
"reminder": "Напоминание",
|
"reminder": "Напоминание",
|
||||||
"rescheduled": "Перенесено",
|
"rescheduled": "Перенесено",
|
||||||
"completed": "Выполнено",
|
"completed": "Завершено",
|
||||||
"reminder_email": "Напоминание: {{eventType}} с {{name}} {{date}}",
|
"reminder_email": "Напоминание: {{eventType}} с {{name}} {{date}}",
|
||||||
"not_triggering_existing_bookings": "Не работает для уже созданных бронирований, так как при бронировании события пользователь должен будет ввести номер телефона.",
|
"not_triggering_existing_bookings": "Не работает для уже созданных бронирований, так как при бронировании события пользователь должен будет ввести номер телефона.",
|
||||||
"minute_one": "{{count}} минута",
|
"minute_one": "{{count}} минута",
|
||||||
@@ -1327,7 +1327,7 @@
|
|||||||
"download_responses_description": "Скачать все ответы пользователей, заполнивших форму, в формате CSV.",
|
"download_responses_description": "Скачать все ответы пользователей, заполнивших форму, в формате CSV.",
|
||||||
"download": "Скачать",
|
"download": "Скачать",
|
||||||
"download_recording": "Скачать запись",
|
"download_recording": "Скачать запись",
|
||||||
"recording_from_your_recent_call": "Запись вашего недавнего созвана в {{appName}} готова для скачивания",
|
"recording_from_your_recent_call": "Запись вашего недавнего созвона в {{appName}} готова для скачивания",
|
||||||
"create_your_first_form": "Создайте первую форму",
|
"create_your_first_form": "Создайте первую форму",
|
||||||
"create_your_first_form_description": "Формы маршрутизации позволяют задавать пользователям уточняющие вопросы, чтобы перенаправлять их к соответствующему лицу или типу события.",
|
"create_your_first_form_description": "Формы маршрутизации позволяют задавать пользователям уточняющие вопросы, чтобы перенаправлять их к соответствующему лицу или типу события.",
|
||||||
"create_your_first_webhook": "Создайте свой первый вебхук",
|
"create_your_first_webhook": "Создайте свой первый вебхук",
|
||||||
@@ -1659,9 +1659,9 @@
|
|||||||
"delete_sso_configuration_confirmation_description": "Удалить конфигурацию {{connectionType}}? Участники команды, входящие в Cal.com через {{connectionType}}, больше не смогут получить к нему доступ.",
|
"delete_sso_configuration_confirmation_description": "Удалить конфигурацию {{connectionType}}? Участники команды, входящие в Cal.com через {{connectionType}}, больше не смогут получить к нему доступ.",
|
||||||
"organizer_timezone": "Часовой пояс организатора",
|
"organizer_timezone": "Часовой пояс организатора",
|
||||||
"email_user_cta": "Посмотреть приглашение",
|
"email_user_cta": "Посмотреть приглашение",
|
||||||
"email_no_user_invite_heading": "Вас пригласили в {{appName}} {{entity}}",
|
"email_no_user_invite_heading": "Вас пригласили в {{entity}} {{appName}}",
|
||||||
"email_no_user_invite_subheading": "{{invitedBy}} пригласил(-а) вас в команду в {{appName}}. {{appName}} — это гибкий планировщик событий, с помощью которого пользователи и целые команды могут планировать встречи без утомительной переписки по электронной почте.",
|
"email_no_user_invite_subheading": "{{invitedBy}} пригласил(-а) вас в команду в {{appName}}. {{appName}} — это гибкий планировщик событий, с помощью которого пользователи и целые команды могут планировать встречи без утомительной переписки по электронной почте.",
|
||||||
"email_user_invite_subheading": "{{invitedBy}} пригласил(а) вас в команду {{entity}} `{{teamName}}` в {{appName}}. {{appName}} — это гибкий планировщик событий, с помощью которого вы и ваша компания {{entity}} можете планировать встречи без утомительной переписки по электронной почте.",
|
"email_user_invite_subheading": "{{invitedBy}} пригласил(а) вас в команду {{entity}} `{{teamName}}` в {{appName}}. {{appName}} — это гибкий планировщик событий, с помощью которого вы и ваша {{entity}} можете планировать встречи без утомительной переписки по электронной почте.",
|
||||||
"email_no_user_invite_steps_intro": "Всего несколько шагов — и вы сможете оперативно и без стресса планировать встречи с {{entity}}.",
|
"email_no_user_invite_steps_intro": "Всего несколько шагов — и вы сможете оперативно и без стресса планировать встречи с {{entity}}.",
|
||||||
"email_no_user_step_one": "Выберите имя пользователя",
|
"email_no_user_step_one": "Выберите имя пользователя",
|
||||||
"email_no_user_step_two": "Подключите аккаунт календаря",
|
"email_no_user_step_two": "Подключите аккаунт календаря",
|
||||||
@@ -1687,7 +1687,7 @@
|
|||||||
"attendee_no_longer_attending": "Участник отказался от посещения вашего мероприятия",
|
"attendee_no_longer_attending": "Участник отказался от посещения вашего мероприятия",
|
||||||
"attendee_no_longer_attending_subtitle": "{{name}} отказался(-ась) от посещения мероприятия. Этот промежуток времени снова свободен",
|
"attendee_no_longer_attending_subtitle": "{{name}} отказался(-ась) от посещения мероприятия. Этот промежуток времени снова свободен",
|
||||||
"create_event_on": "Создать событие в календаре",
|
"create_event_on": "Создать событие в календаре",
|
||||||
"create_routing_form_on": "Создать форму маршрутизации",
|
"create_routing_form_on": "Создать форму маршрутизации в",
|
||||||
"default_app_link_title": "Установить ссылку на приложение по умолчанию",
|
"default_app_link_title": "Установить ссылку на приложение по умолчанию",
|
||||||
"default_app_link_description": "Если установить ссылку на приложение по умолчанию, она будет присваиваться всем вновь создаваемым событиям.",
|
"default_app_link_description": "Если установить ссылку на приложение по умолчанию, она будет присваиваться всем вновь создаваемым событиям.",
|
||||||
"organizer_default_conferencing_app": "Приложение организатора по умолчанию",
|
"organizer_default_conferencing_app": "Приложение организатора по умолчанию",
|
||||||
@@ -1876,16 +1876,16 @@
|
|||||||
"connect_google_workspace": "Подключить Google Workspace",
|
"connect_google_workspace": "Подключить Google Workspace",
|
||||||
"google_workspace_admin_tooltip": "Эту функцию может использовать только администратор Workspace",
|
"google_workspace_admin_tooltip": "Эту функцию может использовать только администратор Workspace",
|
||||||
"first_event_type_webhook_description": "Создайте первый вебхук для этого типа событий",
|
"first_event_type_webhook_description": "Создайте первый вебхук для этого типа событий",
|
||||||
"install_app_on": "Установить приложение на",
|
"install_app_on": "Установить приложение в",
|
||||||
"create_for": "Создать для",
|
"create_for": "Создать для",
|
||||||
"setup_organization": "Настроить организацию",
|
"setup_organization": "Настроить организацию",
|
||||||
"organization_banner_description": "Создайте среду, в которой ваши команды смогут открывать совместный доступ к приложениям, рабочим процессам и типам событий, составляя расписание совместно или по очереди.",
|
"organization_banner_description": "Создавайте рабочие среды, в которых ваши команды смогут открывать совместный доступ к приложениям, рабочим процессам и типам событий, составляя расписание совместно или по очереди.",
|
||||||
"organization_banner_title": "Управляйте организациями с несколькими командами",
|
"organization_banner_title": "Управляйте организациями с несколькими командами",
|
||||||
"set_up_your_organization": "Настройте организацию",
|
"set_up_your_organization": "Настройте организацию",
|
||||||
"organizations_description": "Организация – это общая рабочая среда, в которой команды могут создавать общие типы событий, приложения, рабочие процессы и многое другое.",
|
"organizations_description": "Организация – это общая рабочая среда, в которой команды могут создавать общие типы событий, приложения, рабочие процессы и многое другое.",
|
||||||
"must_enter_organization_name": "Необходимо ввести название организации",
|
"must_enter_organization_name": "Необходимо ввести название организации",
|
||||||
"must_enter_organization_admin_email": "Необходимо ввести адрес электронной почты вашей организации",
|
"must_enter_organization_admin_email": "Необходимо ввести адрес электронной почты вашей организации",
|
||||||
"admin_email": "Адрес электронной почты вашей организации",
|
"admin_email": "Адрес электронной почты в организации",
|
||||||
"admin_username": "Имя пользователя администратора",
|
"admin_username": "Имя пользователя администратора",
|
||||||
"organization_name": "Название организации",
|
"organization_name": "Название организации",
|
||||||
"organization_url": "URL-адрес организации",
|
"organization_url": "URL-адрес организации",
|
||||||
@@ -1912,7 +1912,7 @@
|
|||||||
"organization_admin_invited_body": "Станьте частью команды {{orgName}} – и вы сможете уделять внимание встречам, а не их планированию!",
|
"organization_admin_invited_body": "Станьте частью команды {{orgName}} – и вы сможете уделять внимание встречам, а не их планированию!",
|
||||||
"duplicated_slugs_warning": "Не удалось создать следующие команды из-за дублирующихся слагов: {{slugs}}",
|
"duplicated_slugs_warning": "Не удалось создать следующие команды из-за дублирующихся слагов: {{slugs}}",
|
||||||
"team_names_empty": "Имена команд не могут быть пустыми",
|
"team_names_empty": "Имена команд не могут быть пустыми",
|
||||||
"team_names_repeated": "Имена команд не могут быть повторяться",
|
"team_names_repeated": "Имена команд должны быть уникальными",
|
||||||
"user_belongs_organization": "Пользователь относится к организации",
|
"user_belongs_organization": "Пользователь относится к организации",
|
||||||
"org_no_teams_yet": "У этой организации еще нет команд",
|
"org_no_teams_yet": "У этой организации еще нет команд",
|
||||||
"org_no_teams_yet_description": "Если вы администратор, не забудьте создать команды, которые будут отображаться здесь.",
|
"org_no_teams_yet_description": "Если вы администратор, не забудьте создать команды, которые будут отображаться здесь.",
|
||||||
|
|||||||
@@ -131,7 +131,7 @@
|
|||||||
"upgrade_banner_action": "Nadogradite ovde",
|
"upgrade_banner_action": "Nadogradite ovde",
|
||||||
"team_upgraded_successfully": "Vaš tim je uspešno pretplaćen!",
|
"team_upgraded_successfully": "Vaš tim je uspešno pretplaćen!",
|
||||||
"org_upgrade_banner_description": "Hvala što isprobavate plan naše organizacije. Primetili smo da tim vaše organizacije „{{teamName}}” treba da se nadogradi.",
|
"org_upgrade_banner_description": "Hvala što isprobavate plan naše organizacije. Primetili smo da tim vaše organizacije „{{teamName}}” treba da se nadogradi.",
|
||||||
"org_upgraded_successfully": "Vaša organizacija je uspešno nadograđena!",
|
"org_upgraded_successfully": "Vaš Organization je uspešno nadograđen!",
|
||||||
"use_link_to_reset_password": "Resetujte lozinku koristeći link ispod",
|
"use_link_to_reset_password": "Resetujte lozinku koristeći link ispod",
|
||||||
"hey_there": "Zdravo,",
|
"hey_there": "Zdravo,",
|
||||||
"forgot_your_password_calcom": "Zaboravili ste lozinku? - {{appName}}",
|
"forgot_your_password_calcom": "Zaboravili ste lozinku? - {{appName}}",
|
||||||
|
|||||||
@@ -129,8 +129,8 @@
|
|||||||
"team_upgrade_banner_description": "Tack för att du testade vår nya teamplan. Vi märkte att ditt team \"{{teamName}}\" måste uppgraderas.",
|
"team_upgrade_banner_description": "Tack för att du testade vår nya teamplan. Vi märkte att ditt team \"{{teamName}}\" måste uppgraderas.",
|
||||||
"upgrade_banner_action": "Uppgradera här",
|
"upgrade_banner_action": "Uppgradera här",
|
||||||
"team_upgraded_successfully": "Ditt team har uppgraderats!",
|
"team_upgraded_successfully": "Ditt team har uppgraderats!",
|
||||||
"org_upgrade_banner_description": "Tack för att du testade vår nya organisationsplan. Vi märkte att din organisation \"{{teamName}}\" måste uppgraderas.",
|
"org_upgrade_banner_description": "Tack för att du testade vår nya Organization-plan. Vi märkte att din Organization \"{{teamName}}\" måste uppgraderas.",
|
||||||
"org_upgraded_successfully": "Din organisation har uppgraderats!",
|
"org_upgraded_successfully": "Din Organization har uppgraderats!",
|
||||||
"use_link_to_reset_password": "Använd länken nedan för att återställa ditt lösenord",
|
"use_link_to_reset_password": "Använd länken nedan för att återställa ditt lösenord",
|
||||||
"hey_there": "Hallå där,",
|
"hey_there": "Hallå där,",
|
||||||
"forgot_your_password_calcom": "Glömt ditt lösenord? - {{appName}}",
|
"forgot_your_password_calcom": "Glömt ditt lösenord? - {{appName}}",
|
||||||
@@ -551,7 +551,7 @@
|
|||||||
"team_description": "Några meningar om ditt team. Detta visas på ditt teams URL-sida.",
|
"team_description": "Några meningar om ditt team. Detta visas på ditt teams URL-sida.",
|
||||||
"org_description": "Några meningar om din organisation. Detta kommer att visas på din organisations webbsida.",
|
"org_description": "Några meningar om din organisation. Detta kommer att visas på din organisations webbsida.",
|
||||||
"members": "Medlemmar",
|
"members": "Medlemmar",
|
||||||
"organization_members": "Organisationens medlemmar",
|
"organization_members": "Organization-medlemmar",
|
||||||
"member": "Medlem",
|
"member": "Medlem",
|
||||||
"number_member_one": "{{count}} medlem",
|
"number_member_one": "{{count}} medlem",
|
||||||
"number_member_other": "{{count}} medlemmar",
|
"number_member_other": "{{count}} medlemmar",
|
||||||
@@ -699,7 +699,7 @@
|
|||||||
"create_team_to_get_started": "Skapa ett team för att komma igång",
|
"create_team_to_get_started": "Skapa ett team för att komma igång",
|
||||||
"teams": "Teams",
|
"teams": "Teams",
|
||||||
"team": "Team",
|
"team": "Team",
|
||||||
"organization": "Organisation",
|
"organization": "Organization",
|
||||||
"team_billing": "Team-fakturering",
|
"team_billing": "Team-fakturering",
|
||||||
"team_billing_description": "Hantera fakturering för ditt team",
|
"team_billing_description": "Hantera fakturering för ditt team",
|
||||||
"upgrade_to_flexible_pro_title": "Vi har ändrat fakturering för team",
|
"upgrade_to_flexible_pro_title": "Vi har ändrat fakturering för team",
|
||||||
@@ -1938,7 +1938,7 @@
|
|||||||
"insights_all_org_filter": "Alla",
|
"insights_all_org_filter": "Alla",
|
||||||
"insights_team_filter": "Team: {{teamName}}",
|
"insights_team_filter": "Team: {{teamName}}",
|
||||||
"insights_user_filter": "Användare: {{userName}}",
|
"insights_user_filter": "Användare: {{userName}}",
|
||||||
"insights_subtitle": "Visa bokningsinsikter för dina händelser",
|
"insights_subtitle": "Visa Insights-bokningar för dina händelser",
|
||||||
"custom_plan": "Anpassad plan",
|
"custom_plan": "Anpassad plan",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Lägg till dina nya strängar här ovanför ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Lägg till dina nya strängar här ovanför ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -1938,7 +1938,7 @@
|
|||||||
"insights_all_org_filter": "Tümü",
|
"insights_all_org_filter": "Tümü",
|
||||||
"insights_team_filter": "Ekip: {{teamName}}",
|
"insights_team_filter": "Ekip: {{teamName}}",
|
||||||
"insights_user_filter": "Kullanıcı: {{userName}}",
|
"insights_user_filter": "Kullanıcı: {{userName}}",
|
||||||
"insights_subtitle": "Etkinlikleriniz için rezervasyon analizlerini görüntüleyin",
|
"insights_subtitle": "Etkinlikleriniz için rezervasyon Insights'lerini görüntüleyin",
|
||||||
"custom_plan": "Özel Plan",
|
"custom_plan": "Özel Plan",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "Про команду",
|
"team_info": "Про команду",
|
||||||
"request_another_invitation_email": "Якщо ви не хочете використовувати {{toEmail}} в {{appName}} або вже маєте обліковий запис {{appName}}, надішліть запит на запрошення на потрібну електронну адресу.",
|
"request_another_invitation_email": "Якщо ви не хочете використовувати {{toEmail}} в {{appName}} або вже маєте обліковий запис {{appName}}, надішліть запит на запрошення на потрібну електронну адресу.",
|
||||||
"you_have_been_invited": "Вас запрошено приєднатися до команди «{{teamName}}»",
|
"you_have_been_invited": "Вас запрошено приєднатися до команди «{{teamName}}»",
|
||||||
"user_invited_you": "{{user}} запросив(-ла) вас приєднатися до команди «{{team}}» користувача {{entity}} в {{appName}}",
|
"user_invited_you": "{{user}} запросив(-ла) вас приєднатися сюди: {{entity}} «{{team}}» в {{appName}}",
|
||||||
"hidden_team_member_title": "У цій команді вас приховано",
|
"hidden_team_member_title": "У цій команді вас приховано",
|
||||||
"hidden_team_member_message": "Ваше місце не оплачено. Перейдіть на версію Pro або попросіть власника команди оплатити ваше місце.",
|
"hidden_team_member_message": "Ваше місце не оплачено. Перейдіть на версію Pro або попросіть власника команди оплатити ваше місце.",
|
||||||
"hidden_team_owner_message": "Щоб користуватися функціями команди, потрібен обліковий запис версії Pro. До переходу на цю версію вас буде приховано.",
|
"hidden_team_owner_message": "Щоб користуватися функціями команди, потрібен обліковий запис версії Pro. До переходу на цю версію вас буде приховано.",
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "Thông Tin Nhóm",
|
"team_info": "Thông Tin Nhóm",
|
||||||
"request_another_invitation_email": "Nếu bạn không muốn sử dụng {{toEmail}} là email {{appName}} của bạn hay đã có tài khoản {{appName}}, hãy yêu cầu lời mời sang email đó.",
|
"request_another_invitation_email": "Nếu bạn không muốn sử dụng {{toEmail}} là email {{appName}} của bạn hay đã có tài khoản {{appName}}, hãy yêu cầu lời mời sang email đó.",
|
||||||
"you_have_been_invited": "Bạn đã được mời để gia nhập nhóm {{teamName}}",
|
"you_have_been_invited": "Bạn đã được mời để gia nhập nhóm {{teamName}}",
|
||||||
"user_invited_you": "{{user}} đã mời bạn để gia nhập {{team}} {{entity}} trên {{appName}}",
|
"user_invited_you": "{{user}} đã mời bạn để gia nhập {{entity}} {{team}} trên {{appName}}",
|
||||||
"hidden_team_member_title": "Bạn đã bị ẩn trong nhóm này",
|
"hidden_team_member_title": "Bạn đã bị ẩn trong nhóm này",
|
||||||
"hidden_team_member_message": "Ghế ngồi của bạn không được thanh toán bởi nhóm, hãy nâng cấp lên PRO hoặc thông báo cho người quản lý nhóm để họ có thể thanh toán cho ghế ngồi của bạn.",
|
"hidden_team_member_message": "Ghế ngồi của bạn không được thanh toán bởi nhóm, hãy nâng cấp lên PRO hoặc thông báo cho người quản lý nhóm để họ có thể thanh toán cho ghế ngồi của bạn.",
|
||||||
"hidden_team_owner_message": "Bạn cần tài khoản Pro để sử dụng nhóm, bạn sẽ bị ẩn cho đến khi bạn thanh toán.",
|
"hidden_team_owner_message": "Bạn cần tài khoản Pro để sử dụng nhóm, bạn sẽ bị ẩn cho đến khi bạn thanh toán.",
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
"team_upgrade_banner_description": "Cám ơn bạn đã dùng thử gói kế hoạch mới dành cho nhóm. Chúng tôi để ý thấy nhóm \"{{teamName}}\" của bạn cần được nâng cấp.",
|
"team_upgrade_banner_description": "Cám ơn bạn đã dùng thử gói kế hoạch mới dành cho nhóm. Chúng tôi để ý thấy nhóm \"{{teamName}}\" của bạn cần được nâng cấp.",
|
||||||
"upgrade_banner_action": "Nâng cấp tại đây",
|
"upgrade_banner_action": "Nâng cấp tại đây",
|
||||||
"team_upgraded_successfully": "Nhóm bạn đã được nâng cấp thành công!",
|
"team_upgraded_successfully": "Nhóm bạn đã được nâng cấp thành công!",
|
||||||
"org_upgrade_banner_description": "Cám ơn bạn đã dùng thử gói Tổ chức. Chúng tôi để ý thấy Tổ chức \"{{teamName}}\" của bạn cần được nâng cấp.",
|
"org_upgrade_banner_description": "Cám ơn bạn đã dùng thử gói Organization. Chúng tôi để ý thấy Organization \"{{teamName}}\" của bạn cần được nâng cấp.",
|
||||||
"org_upgraded_successfully": "Tổ chức của bạn đã được nâng cấp thành công!",
|
"org_upgraded_successfully": "Organization của bạn đã được nâng cấp thành công!",
|
||||||
"use_link_to_reset_password": "Sử dụng đường link dưới đây để thay đổi mật khẩu của bạn",
|
"use_link_to_reset_password": "Sử dụng đường link dưới đây để thay đổi mật khẩu của bạn",
|
||||||
"hey_there": "Xin chào,",
|
"hey_there": "Xin chào,",
|
||||||
"forgot_your_password_calcom": "Quên mật khẩu của bạn? - {{appName}}",
|
"forgot_your_password_calcom": "Quên mật khẩu của bạn? - {{appName}}",
|
||||||
@@ -551,7 +551,7 @@
|
|||||||
"team_description": "Một vài câu về nhóm của bạn. Thông tin này sẽ xuất hiện trên trang URL của nhóm của bạn.",
|
"team_description": "Một vài câu về nhóm của bạn. Thông tin này sẽ xuất hiện trên trang URL của nhóm của bạn.",
|
||||||
"org_description": "Một vài câu về tổ chức của bạn. Thông tin này sẽ xuất hiện trên trang URL của tổ chức của bạn.",
|
"org_description": "Một vài câu về tổ chức của bạn. Thông tin này sẽ xuất hiện trên trang URL của tổ chức của bạn.",
|
||||||
"members": "Các thành viên",
|
"members": "Các thành viên",
|
||||||
"organization_members": "Thành viên trong tổ chức",
|
"organization_members": "Thành viên trong Organization",
|
||||||
"member": "Thành viên",
|
"member": "Thành viên",
|
||||||
"number_member_one": "{{count}} thành viên",
|
"number_member_one": "{{count}} thành viên",
|
||||||
"number_member_other": "{{count}} thành viên",
|
"number_member_other": "{{count}} thành viên",
|
||||||
@@ -1327,7 +1327,7 @@
|
|||||||
"download_responses_description": "Tải xuống tất cả phản hồi vào biểu mẫu của bạn ở định dạng CSV.",
|
"download_responses_description": "Tải xuống tất cả phản hồi vào biểu mẫu của bạn ở định dạng CSV.",
|
||||||
"download": "Tải về",
|
"download": "Tải về",
|
||||||
"download_recording": "Tải xuống bản ghi âm",
|
"download_recording": "Tải xuống bản ghi âm",
|
||||||
"recording_from_your_recent_call": "Một bản ghi âm từ cuộc gọi gần đây trên {{appName}} đã sẵn sàng để tải xuống",
|
"recording_from_your_recent_call": "Một bản ghi từ cuộc gọi gần đây trên {{appName}} đã sẵn sàng để tải xuống",
|
||||||
"create_your_first_form": "Tạo biểu mẫu đầu tiên",
|
"create_your_first_form": "Tạo biểu mẫu đầu tiên",
|
||||||
"create_your_first_form_description": "Với Biểu mẫu định hướng, bạn có thể hỏi một số câu sơ tuyển và định hướng đến đúng người hay đúng loại sự kiện.",
|
"create_your_first_form_description": "Với Biểu mẫu định hướng, bạn có thể hỏi một số câu sơ tuyển và định hướng đến đúng người hay đúng loại sự kiện.",
|
||||||
"create_your_first_webhook": "Tạo Webhook đầu tiên",
|
"create_your_first_webhook": "Tạo Webhook đầu tiên",
|
||||||
@@ -1876,10 +1876,10 @@
|
|||||||
"connect_google_workspace": "Kết nối Google Workspace",
|
"connect_google_workspace": "Kết nối Google Workspace",
|
||||||
"google_workspace_admin_tooltip": "Bạn phải là một Quản trị viên Không gian làm việc để dùng tính năng này",
|
"google_workspace_admin_tooltip": "Bạn phải là một Quản trị viên Không gian làm việc để dùng tính năng này",
|
||||||
"first_event_type_webhook_description": "Tạo webhook đầu tiên của bạn cho loại sự kiện này",
|
"first_event_type_webhook_description": "Tạo webhook đầu tiên của bạn cho loại sự kiện này",
|
||||||
"install_app_on": "Cài đặt ứng dụng trên",
|
"install_app_on": "Cài đặt ứng dụng cho",
|
||||||
"create_for": "Tạo cho",
|
"create_for": "Tạo cho",
|
||||||
"setup_organization": "Thiết lập một Tổ chức",
|
"setup_organization": "Thiết lập một Tổ chức",
|
||||||
"organization_banner_description": "Tạo một môi trường tại đó các nhóm của bạn có thể tạo những ứng dụng, tiến độ công việc và loại sự kiện mà có thể chia sẻ được, với chức năng đặt lịch dạng round-robin và tập thể.",
|
"organization_banner_description": "Tạo môi trường tại đó các nhóm của bạn có thể tạo những ứng dụng, tiến độ công việc và loại sự kiện mà có thể chia sẻ được, với chức năng đặt lịch dạng round-robin và tập thể.",
|
||||||
"organization_banner_title": "Quản lý các tổ chức có nhiều nhóm",
|
"organization_banner_title": "Quản lý các tổ chức có nhiều nhóm",
|
||||||
"set_up_your_organization": "Thiết lập tổ chức của bạn",
|
"set_up_your_organization": "Thiết lập tổ chức của bạn",
|
||||||
"organizations_description": "Tổ chức là môi trường chia sẻ tại đó các nhóm có thể tạo loại sự kiện, ứng dụng, tiến độ công việc, v. v. vốn được chia sẻ dùng chung.",
|
"organizations_description": "Tổ chức là môi trường chia sẻ tại đó các nhóm có thể tạo loại sự kiện, ứng dụng, tiến độ công việc, v. v. vốn được chia sẻ dùng chung.",
|
||||||
@@ -1918,7 +1918,7 @@
|
|||||||
"org_no_teams_yet_description": "Nếu bạn là một quản trị viên, hãy bảo đảm tạo nhóm các nhóm cần được hiển thị tại đây.",
|
"org_no_teams_yet_description": "Nếu bạn là một quản trị viên, hãy bảo đảm tạo nhóm các nhóm cần được hiển thị tại đây.",
|
||||||
"set_up": "Thiết lập",
|
"set_up": "Thiết lập",
|
||||||
"set_up_your_profile": "Thiết lập hồ sơ của bạn",
|
"set_up_your_profile": "Thiết lập hồ sơ của bạn",
|
||||||
"set_up_your_profile_description": "Hãy để mọi người biết bạn là ai trong {{orgName}}, và họ biết khi nhấp vào liên kết công cộng của bạn.",
|
"set_up_your_profile_description": "Hãy để mọi người biết bạn là ai trong {{orgName}}, và cho họ biết khi nhấp vào liên kết công cộng của bạn.",
|
||||||
"my_profile": "Hồ sơ của tôi",
|
"my_profile": "Hồ sơ của tôi",
|
||||||
"my_settings": "Cài đặt của tôi",
|
"my_settings": "Cài đặt của tôi",
|
||||||
"crm": "CRM",
|
"crm": "CRM",
|
||||||
@@ -1938,7 +1938,7 @@
|
|||||||
"insights_all_org_filter": "Tất cả",
|
"insights_all_org_filter": "Tất cả",
|
||||||
"insights_team_filter": "Nhóm: {{teamName}}",
|
"insights_team_filter": "Nhóm: {{teamName}}",
|
||||||
"insights_user_filter": "Người dùng: {{userName}}",
|
"insights_user_filter": "Người dùng: {{userName}}",
|
||||||
"insights_subtitle": "Xem số liệu của lịch hẹn ở mọi sự kiện của bạn",
|
"insights_subtitle": "Xem insights của lịch hẹn ở mọi sự kiện của bạn",
|
||||||
"custom_plan": "Gói Tuỳ chỉnh",
|
"custom_plan": "Gói Tuỳ chỉnh",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
"upgrade_banner_action": "在此处升级",
|
"upgrade_banner_action": "在此处升级",
|
||||||
"team_upgraded_successfully": "您的团队升级成功!",
|
"team_upgraded_successfully": "您的团队升级成功!",
|
||||||
"org_upgrade_banner_description": "感谢您试用我们的 Organization 计划。我们注意到您的组织“{{teamName}}”需要升级。",
|
"org_upgrade_banner_description": "感谢您试用我们的 Organization 计划。我们注意到您的组织“{{teamName}}”需要升级。",
|
||||||
"org_upgraded_successfully": "您的组织已成功升级!",
|
"org_upgraded_successfully": "您的 Organization 已成功升级!",
|
||||||
"use_link_to_reset_password": "使用下面的链接重置您的密码",
|
"use_link_to_reset_password": "使用下面的链接重置您的密码",
|
||||||
"hey_there": "嘿,您好!",
|
"hey_there": "嘿,您好!",
|
||||||
"forgot_your_password_calcom": "忘记密码?- {{appName}}",
|
"forgot_your_password_calcom": "忘记密码?- {{appName}}",
|
||||||
@@ -555,7 +555,7 @@
|
|||||||
"team_description": "请写一段简单的团队介绍,该介绍将会显示在您的团队链接页面上。",
|
"team_description": "请写一段简单的团队介绍,该介绍将会显示在您的团队链接页面上。",
|
||||||
"org_description": "关于您的组织的几句话。这将显示在您组织的链接页面上。",
|
"org_description": "关于您的组织的几句话。这将显示在您组织的链接页面上。",
|
||||||
"members": "成员",
|
"members": "成员",
|
||||||
"organization_members": "组织成员",
|
"organization_members": "Organization 成员",
|
||||||
"member": "成员",
|
"member": "成员",
|
||||||
"number_member_one": "{{count}} 个成员",
|
"number_member_one": "{{count}} 个成员",
|
||||||
"number_member_other": "{{count}} 个成员",
|
"number_member_other": "{{count}} 个成员",
|
||||||
@@ -1331,7 +1331,7 @@
|
|||||||
"download_responses_description": "以 CSV 格式下载对表格的所有回复。",
|
"download_responses_description": "以 CSV 格式下载对表格的所有回复。",
|
||||||
"download": "下载",
|
"download": "下载",
|
||||||
"download_recording": "下载录制内容",
|
"download_recording": "下载录制内容",
|
||||||
"recording_from_your_recent_call": "您最近在 {{appName}} 上的通话录音可供下载",
|
"recording_from_your_recent_call": "您最近在 {{appName}} 上的通话录制内容可供下载",
|
||||||
"create_your_first_form": "创建您的第一个表格",
|
"create_your_first_form": "创建您的第一个表格",
|
||||||
"create_your_first_form_description": "利用途径表格,您可以提出符合条件的问题,并可根据途径找到正确的人或活动类型。",
|
"create_your_first_form_description": "利用途径表格,您可以提出符合条件的问题,并可根据途径找到正确的人或活动类型。",
|
||||||
"create_your_first_webhook": "创建您的第一个 Webhook",
|
"create_your_first_webhook": "创建您的第一个 Webhook",
|
||||||
@@ -1691,7 +1691,7 @@
|
|||||||
"attendee_no_longer_attending": "一名参与者不再参加您的活动",
|
"attendee_no_longer_attending": "一名参与者不再参加您的活动",
|
||||||
"attendee_no_longer_attending_subtitle": "{{name}} 已取消。这意味着该时段有一个位置空出来",
|
"attendee_no_longer_attending_subtitle": "{{name}} 已取消。这意味着该时段有一个位置空出来",
|
||||||
"create_event_on": "创建活动于",
|
"create_event_on": "创建活动于",
|
||||||
"create_routing_form_on": "创建途径表格于",
|
"create_routing_form_on": "创建途径表格的账户",
|
||||||
"default_app_link_title": "设置默认应用链接",
|
"default_app_link_title": "设置默认应用链接",
|
||||||
"default_app_link_description": "设置默认应用链接可以让所有新创建的活动类型使用您设置的应用链接。",
|
"default_app_link_description": "设置默认应用链接可以让所有新创建的活动类型使用您设置的应用链接。",
|
||||||
"organizer_default_conferencing_app": "组织者的默认应用",
|
"organizer_default_conferencing_app": "组织者的默认应用",
|
||||||
@@ -1880,7 +1880,7 @@
|
|||||||
"connect_google_workspace": "连接 Google Workspace",
|
"connect_google_workspace": "连接 Google Workspace",
|
||||||
"google_workspace_admin_tooltip": "您必须是 Workspace 管理员才能使用此功能",
|
"google_workspace_admin_tooltip": "您必须是 Workspace 管理员才能使用此功能",
|
||||||
"first_event_type_webhook_description": "为此活动类型创建第一个 Webhook",
|
"first_event_type_webhook_description": "为此活动类型创建第一个 Webhook",
|
||||||
"install_app_on": "安装应用在",
|
"install_app_on": "安装应用的账户",
|
||||||
"create_for": "创建",
|
"create_for": "创建",
|
||||||
"setup_organization": "设置组织",
|
"setup_organization": "设置组织",
|
||||||
"organization_banner_description": "创建一个环境,让团队可以在其中通过轮流和集体日程安排来创建共享的应用、工作流程和活动类型。",
|
"organization_banner_description": "创建一个环境,让团队可以在其中通过轮流和集体日程安排来创建共享的应用、工作流程和活动类型。",
|
||||||
@@ -1942,7 +1942,7 @@
|
|||||||
"insights_all_org_filter": "所有应用",
|
"insights_all_org_filter": "所有应用",
|
||||||
"insights_team_filter": "团队:{{teamName}}",
|
"insights_team_filter": "团队:{{teamName}}",
|
||||||
"insights_user_filter": "用户:{{userName}}",
|
"insights_user_filter": "用户:{{userName}}",
|
||||||
"insights_subtitle": "查看您的活动的预约洞察",
|
"insights_subtitle": "查看您的活动的预约 insights",
|
||||||
"custom_plan": "自定义计划",
|
"custom_plan": "自定义计划",
|
||||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
"team_info": "團隊資訊",
|
"team_info": "團隊資訊",
|
||||||
"request_another_invitation_email": "如果不想要使用 {{toEmail}} 來當作用在 {{appName}} 的電子郵件,或已有 {{appName}} 帳號,請另外索取該電信箱的邀請。",
|
"request_another_invitation_email": "如果不想要使用 {{toEmail}} 來當作用在 {{appName}} 的電子郵件,或已有 {{appName}} 帳號,請另外索取該電信箱的邀請。",
|
||||||
"you_have_been_invited": "收到加入 {{teamName}} 團隊的邀請",
|
"you_have_been_invited": "收到加入 {{teamName}} 團隊的邀請",
|
||||||
"user_invited_you": "{{user}} 已邀請您加入 {{appName}} 上的 {{entity}}{{team}} 團隊",
|
"user_invited_you": "{{user}} 已邀請您加入 {{appName}} 上的 {{entity}}{{team}}",
|
||||||
"hidden_team_member_title": "在團隊裡是隱藏的",
|
"hidden_team_member_title": "在團隊裡是隱藏的",
|
||||||
"hidden_team_member_message": "此座位尚未付費。請升級至 Pro,或通知團隊主持人協助付費。",
|
"hidden_team_member_message": "此座位尚未付費。請升級至 Pro,或通知團隊主持人協助付費。",
|
||||||
"hidden_team_owner_message": "要有 Pro 帳號才可以使用團隊,在升級之前都是隱藏的。",
|
"hidden_team_owner_message": "要有 Pro 帳號才可以使用團隊,在升級之前都是隱藏的。",
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
"team_upgrade_banner_description": "謝謝您試用我們新的團隊方案。我們注意到您的團隊「{{teamName}}」需要升級。",
|
"team_upgrade_banner_description": "謝謝您試用我們新的團隊方案。我們注意到您的團隊「{{teamName}}」需要升級。",
|
||||||
"upgrade_banner_action": "在此處升級",
|
"upgrade_banner_action": "在此處升級",
|
||||||
"team_upgraded_successfully": "團隊成功升級!",
|
"team_upgraded_successfully": "團隊成功升級!",
|
||||||
"org_upgrade_banner_description": "謝謝您試用我們的團隊方案。我們注意到您的組織「{{teamName}}」需要升級。",
|
"org_upgrade_banner_description": "謝謝您試用我們的 Organization 方案。我們注意到您的組織「{{teamName}}」需要升級。",
|
||||||
"org_upgraded_successfully": "組織成功升級!",
|
"org_upgraded_successfully": "組織成功升級!",
|
||||||
"use_link_to_reset_password": "使用以下連結重置密碼",
|
"use_link_to_reset_password": "使用以下連結重置密碼",
|
||||||
"hey_there": "哈囉,",
|
"hey_there": "哈囉,",
|
||||||
@@ -1661,7 +1661,7 @@
|
|||||||
"email_user_cta": "檢視邀請",
|
"email_user_cta": "檢視邀請",
|
||||||
"email_no_user_invite_heading": "您已獲邀加入 {{appName}} {{entity}}",
|
"email_no_user_invite_heading": "您已獲邀加入 {{appName}} {{entity}}",
|
||||||
"email_no_user_invite_subheading": "{{invitedBy}} 已邀請您加入對方在 {{appName}} 上的團隊。{{appName}} 是活動多工排程工具,可讓您和您的團隊無須透過繁複的電子郵件往來就能輕鬆預定會議。",
|
"email_no_user_invite_subheading": "{{invitedBy}} 已邀請您加入對方在 {{appName}} 上的團隊。{{appName}} 是活動多工排程工具,可讓您和您的團隊無須透過繁複的電子郵件往來就能輕鬆預定會議。",
|
||||||
"email_user_invite_subheading": "{{invitedBy}} 已邀請您加入對方在 {{appName}} 上的 {{entity}}「{{teamName}}」團隊。{{appName}} 為一款活動多功能排程工具,可讓您和 {{entity}} 無須透過繁複的電子郵件往來,就能輕鬆預定會議。",
|
"email_user_invite_subheading": "{{invitedBy}} 已邀請您加入對方在 {{appName}} 上的「{{teamName}}」{{entity}}。{{appName}} 為一款活動多功能排程工具,可讓您和 {{entity}} 無須透過繁複的電子郵件往來,就能輕鬆預定會議。",
|
||||||
"email_no_user_invite_steps_intro": "我們會逐步引導您完成幾個簡短的步驟,然後您就能馬上與 {{entity}} 享受沒有壓力的排程預定功能。",
|
"email_no_user_invite_steps_intro": "我們會逐步引導您完成幾個簡短的步驟,然後您就能馬上與 {{entity}} 享受沒有壓力的排程預定功能。",
|
||||||
"email_no_user_step_one": "選擇使用者名稱",
|
"email_no_user_step_one": "選擇使用者名稱",
|
||||||
"email_no_user_step_two": "連結行事曆帳號",
|
"email_no_user_step_two": "連結行事曆帳號",
|
||||||
@@ -1687,7 +1687,7 @@
|
|||||||
"attendee_no_longer_attending": "一位與會者不再參加您的活動",
|
"attendee_no_longer_attending": "一位與會者不再參加您的活動",
|
||||||
"attendee_no_longer_attending_subtitle": "{{name}} 已取消,這代表此時段空出了一個座位",
|
"attendee_no_longer_attending_subtitle": "{{name}} 已取消,這代表此時段空出了一個座位",
|
||||||
"create_event_on": "活動建立日期",
|
"create_event_on": "活動建立日期",
|
||||||
"create_routing_form_on": "建立引導表單於",
|
"create_routing_form_on": "引導表單建立位置",
|
||||||
"default_app_link_title": "設定預設應用程式連結",
|
"default_app_link_title": "設定預設應用程式連結",
|
||||||
"default_app_link_description": "設定預設應用程式連結,即可讓所有全新建立的活動類型使用您設定的應用程式連結。",
|
"default_app_link_description": "設定預設應用程式連結,即可讓所有全新建立的活動類型使用您設定的應用程式連結。",
|
||||||
"organizer_default_conferencing_app": "主辦者的預設應用程式",
|
"organizer_default_conferencing_app": "主辦者的預設應用程式",
|
||||||
@@ -1893,7 +1893,7 @@
|
|||||||
"organization_verify_email_body": "請使用以下驗證碼驗證您的電子郵件地址,以便繼續設定您的組織。",
|
"organization_verify_email_body": "請使用以下驗證碼驗證您的電子郵件地址,以便繼續設定您的組織。",
|
||||||
"additional_url_parameters": "其他網址參數",
|
"additional_url_parameters": "其他網址參數",
|
||||||
"about_your_organization": "關於您的組織",
|
"about_your_organization": "關於您的組織",
|
||||||
"about_your_organization_description": "您可在組織這個共用環境中建立多個團隊,包括共用成員、活動類型、應用程式、工作流程等。",
|
"about_your_organization_description": "您可在組織這個共用環境中建立多個團隊,包括共享成員、活動類型、應用程式、工作流程等。",
|
||||||
"create_your_teams": "建立您的團隊",
|
"create_your_teams": "建立您的團隊",
|
||||||
"create_your_teams_description": "將團隊成員新增到組織,開始一起排程",
|
"create_your_teams_description": "將團隊成員新增到組織,開始一起排程",
|
||||||
"invite_organization_admins": "邀請組織管理員",
|
"invite_organization_admins": "邀請組織管理員",
|
||||||
@@ -1910,7 +1910,7 @@
|
|||||||
"email_already_used": "電子郵件已有人使用",
|
"email_already_used": "電子郵件已有人使用",
|
||||||
"organization_admin_invited_heading": "您已獲邀加入 {{orgName}}",
|
"organization_admin_invited_heading": "您已獲邀加入 {{orgName}}",
|
||||||
"organization_admin_invited_body": "加入您在 {{orgName}} 的團隊,開始專注於會議本身,不必費心於會議的前置作業!",
|
"organization_admin_invited_body": "加入您在 {{orgName}} 的團隊,開始專注於會議本身,不必費心於會議的前置作業!",
|
||||||
"duplicated_slugs_warning": "由於重複的 slugs,下列團隊無法建立:{{slugs}}",
|
"duplicated_slugs_warning": "由於 slug 重複,無法建立下列團隊:{{slugs}}",
|
||||||
"team_names_empty": "團隊名稱不得留空",
|
"team_names_empty": "團隊名稱不得留空",
|
||||||
"team_names_repeated": "團隊名稱不得重複",
|
"team_names_repeated": "團隊名稱不得重複",
|
||||||
"user_belongs_organization": "使用者屬於組織",
|
"user_belongs_organization": "使用者屬於組織",
|
||||||
|
|||||||
@@ -31,5 +31,7 @@ export async function ssrInit(context: GetServerSidePropsContext) {
|
|||||||
// Provides a better UX to the users who have already upgraded.
|
// Provides a better UX to the users who have already upgraded.
|
||||||
await ssr.viewer.teams.hasTeamPlan.prefetch();
|
await ssr.viewer.teams.hasTeamPlan.prefetch();
|
||||||
|
|
||||||
|
await ssr.viewer.public.session.prefetch();
|
||||||
|
|
||||||
return ssr;
|
return ssr;
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
/* Content/Text */
|
/* Content/Text */
|
||||||
--cal-text-emphasis: #f3f4f6;
|
--cal-text-emphasis: #f3f4f6;
|
||||||
--cal-text: #d6d6d6;
|
--cal-text: #d6d6d6;
|
||||||
--cal-text-subtle: #A5a5a5;
|
--cal-text-subtle: #a5a5a5;
|
||||||
--cal-text-muted: #575757;
|
--cal-text-muted: #575757;
|
||||||
--cal-text-inverted: #101010;
|
--cal-text-inverted: #101010;
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
color: var(--cal-brand-text);
|
color: var(--cal-brand-text);
|
||||||
background: var(--cal-brand);
|
background: var(--cal-brand);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -108,8 +108,6 @@ body {
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Desktop App specific CSS
|
Desktop App specific CSS
|
||||||
https://docs.todesktop.com/
|
https://docs.todesktop.com/
|
||||||
@@ -170,17 +168,17 @@ html.todesktop aside {
|
|||||||
margin: 0px -6px;
|
margin: 0px -6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.todesktop-platform-darwin .desktop-transparent{
|
html.todesktop-platform-darwin .desktop-transparent {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.todesktop-platform-darwin.dark main.bg-default{
|
html.todesktop-platform-darwin.dark main.bg-default {
|
||||||
background: rgba(0,0,0,0.6) !important
|
background: rgba(0, 0, 0, 0.6) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.todesktop-platform-darwin.light main.bg-default{
|
html.todesktop-platform-darwin.light main.bg-default {
|
||||||
background: rgba(255,255,255,0.8) !important
|
background: rgba(255, 255, 255, 0.8) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -247,13 +245,10 @@ select:focus {
|
|||||||
border-color: var(--brand-color);
|
border-color: var(--brand-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
.scroll-bar {
|
.scroll-bar {
|
||||||
@apply scrollbar-thin scrollbar-thumb-rounded-md dark:scrollbar-thumb-darkgray-300 scrollbar-thumb-gray-300 scrollbar-track-transparent;
|
@apply scrollbar-thin scrollbar-thumb-rounded-md dark:scrollbar-thumb-darkgray-300 scrollbar-thumb-gray-300 scrollbar-track-transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: avoid global specific css */
|
/* TODO: avoid global specific css */
|
||||||
@@ -261,7 +256,6 @@ select:focus {
|
|||||||
transform: translateX(16px);
|
transform: translateX(16px);
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
/* slider */
|
/* slider */
|
||||||
.slider {
|
.slider {
|
||||||
@@ -512,5 +506,5 @@ select:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.react-tel-input .flag-dropdown {
|
.react-tel-input .flag-dropdown {
|
||||||
@apply !border-r-default !border-y-0 !border-l-0 left-0.5;
|
@apply !border-r-default left-0.5 !border-y-0 !border-l-0;
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,5 @@ const base = require("@calcom/config/tailwind-preset");
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
...base,
|
...base,
|
||||||
content: [...base.content, "../../node_modules/@tremor/**/*.{js,ts,jsx,tsx}"],
|
content: [...base.content, "../../node_modules/@tremor/**/*.{js,ts,jsx,tsx}"],
|
||||||
|
plugins: [...base.plugins, require("tailwindcss-animate")],
|
||||||
};
|
};
|
||||||
Loaded 100 of 396 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user