Compare commits

...
33 Commits
Author SHA1 Message Date
GitHub Actions 23d9788dce chore: release v5.0.6
Post release / release (push) Canceled after 0s
2025-02-24 22:08:05 +00:00
caade0850a fix: consider sendToAll settings in routingForms response (#18226)
* update to consider sendToAll

* added tests for team routingForms selectAllMembers cases

* chore

* chore

* chore

* updated test case in case of toggle off

* tweak

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: unknown <adhabal2002@gmail.com>
2025-02-24 17:59:54 +00:00
Eunjae Lee f6af6e34bd Revert "fix: replace filter implementations on bookings (#19445)" (#19506)
This reverts commit 641193bd61.
2025-02-24 17:14:06 +00:00
Benny Joo 5f5cfaf7c7 perf: improve matching paths in middleware (#19491)
* perf: exclude next native paths from going through middleware

* fix build error

* fix

* fix
2025-02-24 16:53:06 +00:00
07a4aa6c7d fix: Fix for 'Scheduling by cal.com' is still showing in workflow emails even when branding is disabled (#18862)
* Branding Disabling on Team Workflows and Organization Workflows if branding is hidden

* update

* update

---------

Co-authored-by: unknown <adhabal2002@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 16:31:32 +00:00
Eunjae Lee 641193bd61 fix: replace filter implementations on bookings (#19445)
* fix: replace filter implementation on /bookings

* add eventTypeId column

* add eventType filter

* add team filter

* add people filter

* fix type error

* support date range filter

* fix empty view

* fix date range filter

* add comment

* fix type error

* fix type error

* fix type error

* fix type error

* fix type error

* address feedback

* remove reverted functionality
2025-02-24 17:11:40 +01:00
Eunjae Lee 2d372746d3 fix: /bookings get handler (#19369)
* fix: sorting on /bookings

* fix type erorr

* add filters to logging

* fix type error

* filter with attendee emails

* clean up filters

* add test from #19376

* fix e2e tests

* split ORs into smaller queries

* add missing imports
2025-02-24 13:11:29 -03:00
Peer Richelsen 4b2265c35d chore: removed experimental calcom license api call (#19366) 2025-02-24 14:58:25 +00:00
Peer Richelsen 4dc2d3236d Update .env.example (#19364) 2025-02-24 14:55:43 +00:00
+20 7bff15cc47 chore: replace toaster with sonner (#19342)
* fix: replace react-hot-toast with sonner for toast notifications

* feat: add country code (#19264)

* perf: Move PlainChat up the hierarchy to remove rerenders (#19255)

* perf: Move PlainChat up the hierarchy to remove rerenders

* rmeove yarn lock

---------

Co-authored-by: Nizzy <nizabizaher@gmail.com>
Co-authored-by: nizzy <140507264+nizzyabi@users.noreply.github.com>

* hotfix (#19266)

* chore: release v4.9.11

* Handle cancelled status (#19272)

* feat: Use new /routing URL for routing forms (#19235)

* feat: Use new /routing URL for routing forms

* Fixes

* Fix bug

* precent crash

---------

Co-authored-by: Hariom Balhara <hariombalhara@gmgmail.com>

* fix: remove section on /bookings if no data exists (#19261)

* feat: v2 slots new version (#18758)

* refactor: version old slots

* feat: init new slots endpoints

* chore: range format

* fix: duratin

* fix: duratin

* test: slot releaseAt

* refactor: reserve slot response

* refactor variable name

* docs: have new slots controller in docs

* feat: crud for slots reservations

* refactor: use exclude all for response

* docs

* chore: slots input service

* refactor mini

* refactor: remove unused imports

* docs

* handle orgSlug for dynamic events

* refactor: correct name

* docs

* add optional organizationSlug to BySlug search

* refactor: slot output format

* refactor: return seated slot info

* docs

* rename functions

* refactor: slots seated response

* fix: handle same username in org and non org

* refactor: test format

* fix: allow reservationDuration only for authed requests

* chore: check if auth user has permissions to define custom reservation duration

* refactor: split e2e test files

* refactor: invalid request exception codes

* chore: old slots controller uses all old versions

* refactor: remove depreceated fields (#19279)

* refactor: remove depreceated fields

* chore: use v2 endpoint

* chore: update V2 Api type

* chore

* chore: Refactor to remove `getServerSideProps` for /teams route (#19286)

* remove getServerSideProps

* refactor teams route

* chore: release v4.9.12

* fix: Salesforce - if no contact throw Error (#19271)

* Throw error if no contact is passed to createEvent

* chore: update error message

* chore

---------

Co-authored-by: Udit Takkar <udit222001@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>

* fix: missing await router controller (#19276)

* fix: Default people filter in bookings list for admin (#18035)

* default people filter for admin

* chore

* type check

* added test case

* made test concise to reduce flakiness

* add timeout to wait for second get response before counting

* update timeout

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* feat: add CSAT to V2 bookings return (#19278)

* init

* test: v2 bookings returns rating

---------

Co-authored-by: supalarry <laurisskraucis@gmail.com>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>

* chore: disable v2 booking seats safe parse error logs (#19292)

* revert: Reapply "fix: Multiple rr-hosts combine to create erroneous availabil… (#19263)

* Reapply "fix: Multiple rr-hosts combine to create erroneous availability (#18772)"

This reverts commit 5dbc6d9ca6.

* Only thing left is a diff to show which slots are removed

* Add logging around time slot results

* Setup logging through axiom

* .... forgot

* fix: type errors

* Only log when there are differences

* Updated from old which had a failing test to new logic

* chore: release v4.9.13

* fix: flaky test (#19294)

* fix: flaky test

* fix another test

* update

---------

Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: unknown <adhabal2002@gmail.com>

* chore: calendars controller v2 docs (#19291)

Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>

* Merge branch 'main' into replace-toaster-with-sonner

* add ireland country code (#19117)

Co-authored-by: CarinaWolli <wollencarina@gmail.com>

* perf: separate client vs server code from insights layout (#19285)

* add UpgradeTipWrapper

* refactor insights/layout.tsx

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>

* feat: Use Folders to organize SMS links on Dub (#19248)

* feat: Use Folders to organize SMS links on Dub

* Update yarn.lock

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>

* fix: removing-all-members-toggle-for-fh (#19277)

* fix : removing all members toggle for fh

* ux enhancements

* adding placeholder

* chore: release v5.0.0

* fix flake (#19306)

* chore: migrate `/apps/routing-forms/[...pages]` to App Router (#18956)

* wip

* fix

* fix

* refactor

* rename to routingServerSidePropsConfig

* refactor

* refactor

* add routing-link to useIsBookingPage hook

* remove Head component

* fix

* redirect user to apps/routing-forms/forms if user goes to apps/routing-forms

* refactor

* remove log

* remove client component not needed

* clean up code

* remove unneeded metadata

* clean up further

* clean up further 2

* fix type check

* routing-link does not need shell

* Fix title for Routing Form public link and also remove any

* Remove ; in HTML

* Remove unnecessary page reload

---------

Co-authored-by: Hariom Balhara <hariombalhara@gmgmail.com>

* chore: migrate api for team upgrade to App Router (#19100)

* remove old pages router api

* add new app router api

* fix

* fix redirect

* refactor

* fix: cut off and alignment bug (#19317)

* fix: assignment label cut-off

* fix: add all team members label is vertically aligned

* fix: nested scrolls on /bookings (#19284)

* fix: Can't change availability for managed event type (#19006)

* fix: flaky test organization.spec

* fix

* fix: bulk-update-in-scheduleId-in-detailed-view (#19295)

* fix: bulk-update-in-scheduleId-in-detailed-view

* minor-change

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>

* feat: prevent automatic query parameters when opening booking page (#18132)

- Resolve the user hindrance where the event's booking page should not have search parameters such as date and month in the initial page load
- Contains changes for the fix of issue #18094 as well as it is needed

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>

* feat: atoms adjustments with ui v3 styles (#19320)

* refactor: Clean out old code, no longer needed (#19323)

* refactor: Clean out old code, no longer needed

* Removed a sneaky one keen to stay behind

* chore: release v5.0.1

* feat: Create `UserCreationService` and use in API V1 create user endpoint (#19150)

* Create `createUser` method in `userCreationService`

* Refactor `UserRepository` create method to accept prisma input and remove business logic

* API use `UserCreationService`

* Move slugify to service

* Use hashPassword instead

* Type fixes in `UserCreationService`

* Add `userCreationService` tests

* API accept data object

* Type fixes

* Add user _post test

* Add test for locked user

* Add locked param to log

* Add user repository tests

* Do not return locked status

* Explicitly pass `locked` prop

* Fix tests when locked isn't returned

* Fix tests

* Pass locked prop

* Edit test name

* Use logger

* Fix passing hashed password

* fix (#19298)

* fix: timezone input text is now visible in dark mode (#19325)

* feat: make first tab active by default (#19315)

* feat: make first tab active by default

* perf: optimize event types tabs rendering with useMemo

---------

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>

* perf: Use one PageWrapper instance for all settings pages (#18752)

* add a layoutfile to use-page-wrapper route group

* refactor and move bookings status page to route group

* improve logic in pagesAndRewritePaths

* fix

* add use client directive

* move /403 and /500

* move /auth/error

* move /connect-and-join

* move /enterprise

* move /maintenance

* move /more

* move /upgrade

* chore: remove WithLayout from 8 low-risk single pages (#18745)

* move /403 and /500

* move /auth/error

* move /connect-and-join

* move /enterprise

* move /maintenance

* move /more

* move /upgrade

* move /availability pages

* move /event-types pages

* move /insights pages

* move /apps to use-page-wrapper group

* move /getting-started to use-page-wrapper group

* move /signup to use-page-wrapper group

* move /workflows to use-page-wrapper group

* move /video pages to use-page-wrapper group

* pass dehydratedState in layout

* pass dehydratedState in layout

* move settings/(settings-layout) to use-page-wrapper

* move settings/(admin-layout) to use-page-wrapper

* move remaining settings pages to (use-page-wrapper)

* fix test

* remove unused code

* remove unused files

* fix type check

* remove test tag

* remove page

* RSC should not default export client components

* fix: Can't use unsaved booking question as variable in event name (#18604)

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>

* chore: remove WithLayout from not-found.tsx (#19331)

* fix: redirect logic in /settings/admin/apps (#19332)

* chore: v3 fixed filters, new profile view (#19312)

* fixed filters with badge

* aligned recurrence in bookings

* removed new badge

* new profile view

* fixed try for free button

* fixed form input

* fix: Issues with date changes in column view (#19258)

* fix: coulmn view date change

* Update store.ts

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>

* chore: fixed tooltip position for routing form (#19267)

* fixed tooltip position for routing form

* fixed offset

* fix: Fairness when routing (#18550)

* Partial push of new filters

* Let's always return the passed host array when a filter doesn't need to be applied

* fix: isFixed typing in same round robin host check

* Add main bulk of rewritten logic for routed fairness support

* Remove console.log

* Add getAttributeWithEnabledWeights to AttributeRepository

* Add OOO entry repository

* Use getOrderedListOfLuckyUsers in lead threshold filtering

* Shortfall already includes weight

* test against minShortfall

* first attempt to fix fallbacks

* Added testcase updates

* Partially fix filterHosts test

* Some test updates

* Removed email field from normalization

* fix no available users found error

* fix unit test

* remove fallback from same host reschedule return

* fixes and improvements for findQualifiedHosts

* include fallback logic in handleNewBooking

* use fallback in handleNewBooking

* fix for contact owner in handleNewBooking

* WIP - comment

* pass routingFormResponseId

* fix type error

* pass routingFormResponse

* fixes in treshold logic

* remove reason

* merge qualified and fallback availabilities

* fix type error

* add and fix tests

* clean up test file

* fix filterHostsBySameRoundRobinHost tests

* fix findQualifiedHosts.test.ts

* fix getRoutedUsers.test.ts

* fix tests

* fix isRerouting check

* fix start time for two weeks check

* fix fallback hosts

* fix test

* fallback hosts should also include qualified hosts

* fix type error

* fix typos

* add contact owner to fallbacks

* fix typo

* fix qualifiedRRUsers

* set fixed users when no hosts

* add tets + code clean up

* add test for reschedule with same host

* fix typo

* add more tests for findQualifiedHosts

* remove skip from test

* add comment

* remove unused code

* fix fallback users in loadAndValidateUsers

* improve naming for fallback

* rename missed fallback variable

* fix reschedule with same rr host in handleNewBooking

* fixes for fallback slots

* add more tests + small fixes for contact owner

* fix tests and type errors

* add logs for fallback

* add type:json to logger

* Fix small merge issue

* fix end time if two weeks are cut off

* add more tests for contact owner availability check

* add new logic for two weeks fallback

* fix reschedule same RR host test

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* fix: EditLocationDialog footer positioning and structure (#19335)

* fix: EditLocationDialog footer positioning and structure

* fix: make RescheduleDialog footer layout and button structure right

* fix: input dialogue glitch now works great

* made tests happy

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* Merge branch 'main' into replace-toaster-with-sonner

* chore: remove DefaultToast from toast.stories.mdx

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Nizzy <nizabizaher@gmail.com>
Co-authored-by: nizzy <140507264+nizzyabi@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: GitHub Actions <github-actions@github.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmgmail.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: Udit Takkar <udit222001@gmail.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Vijay <vijayraghav22@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: unknown <adhabal2002@gmail.com>
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Steven Tey <stevensteel97@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: amrit <iamamrit27@gmail.com>
Co-authored-by: Sanchit Tewari <46245135+sanchitttt@users.noreply.github.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
2025-02-24 11:48:38 -03:00
luzpaz 97ef32f7ca fix: typos in several package/ directories (#19495)
* fix: typos in packages/embeds
Found via codespell

* fix: typos in packages/lib
Found via codespell

* fix: typos in packages/trpc
Found via codespell
2025-02-24 14:44:08 +00:00
16a94fe712 chore: bump alby packages (#18406)
* chore: bump alby packages

* fix: update alby sdk version

* chore: update yarn.lock

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: amrit <iamamrit27@gmail.com>
2025-02-24 11:25:20 -03:00
Cao HoangandAnik Dhabal Babu 8f29811d5a fix: Some errors breaking storybook build (#18767)
* fix: filters ui breaking in routing insights page

* fix: story book build errors

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 14:24:33 +00:00
Benny Joo a47cd5b106 chore: cleanup - Remove WithLayout HoC itself (#19490)
* remove future folder

* remove unused file

* remove unused files
2025-02-24 08:38:47 -05:00
Eunjae Lee 64aa19fcea revert: default people filter at bookings (#19486) 2025-02-24 14:31:00 +01:00
7c71b179c8 feat: extract bottom navigation logic into a custom hook (#19468)
* feat: extract bottom navigation logic into a custom hook

* tweak

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: unknown <adhabal2002@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 13:27:24 +00:00
luzpaz d485e5f621 fix: typos in packages/app-store (#19470)
Found via `codespell -q 3 -S "*.svg,./apps/web/public/static/locales,./packages/app-store/stripepayment/lib/currencyOptions.ts,./packages/lib/freeEmailDomainCheck/freeEmailDomains.ts" -L afterall,atleast,datea,fo,incase,ist,nam,notin,optionel,perview,reccuring`
2025-02-24 10:54:28 +00:00
Vijay aa8d0f78d6 error msg when end date not selected (#19485) 2025-02-24 10:26:32 +00:00
Sy SagarandAnik Dhabal Babu 564497ec2a feat(lexicalEditor): custom enter-key plugin (#15952)
* fix(team-description): break lines rendering

* chore(EventTypeDescription): useBreakLine hook for handling html line breaks

* feat(lexicalEditor): custom enter-key plugin

* test(customEditorPlugin): enter key usage

* Update customEnterKeyPlugin.tsx

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 14:12:12 +05:30
Anwar SadathandAnik Dhabal Babu 2089ad40ea fix: Wrong avatars shown in webhooks page (#19386)
* fix: Wrong avatars shown in webhooks page

* Fix teams showing wrong avatar

* Fix type error

* Remove unused function arguments

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 08:02:57 +00:00
42e94cd5b7 fix: Misaligned Select with input box (#19400)
* Aligned Select field with input

* Minor fix in alignment

---------

Co-authored-by: amrit <iamamrit27@gmail.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2025-02-24 07:54:48 +00:00
Peer Richelsen 4546bd8653 Update EnterpriseLicense.tsx (#19363) 2025-02-24 12:10:14 +05:30
Anik Dhabal Babu 2a89a5e249 fix: Username input field not in line (#19480) 2025-02-23 18:32:52 +00:00
Benny Joo aba7c6df7f perf: move all booking pages into (booking-page-wrapper) route group (#19321)
* update useIsBookingPage

* move team pages into use-page-wrapper route group

* update imports

* fix type check

* update

* update

* remove isBookingPage configure from booking client components

* move all booking pages to use-page-wrapper route group

* add checkIfBookingPage util

* update layout

* update AppProviders

* improve comments

* update

* update pagesAndRewritePaths logic

* refactor
2025-02-23 10:13:11 +01:00
Peer Richelsen 97348e2052 fixed FAB (#19469) 2025-02-23 03:34:58 -05:00
Steven Tey 30149dd100 Upgrade dub version (#19472) 2025-02-22 22:43:32 +00:00
Peer Richelsen d91ccd37e0 Revert "fixed FAB size (#19466)" (#19467)
This reverts commit 0bd90d1673.
2025-02-22 11:52:58 +00:00
Peer Richelsen 0bd90d1673 fixed FAB size (#19466) 2025-02-22 10:08:16 +00:00
Calcom BotandLingo.dev 6899b853ee feat: update translations via @lingodotdev (#19462)
Co-authored-by: Lingo.dev <support@lingo.dev>
2025-02-21 21:50:02 +00:00
Benny Joo b07d81d0b9 perf: do not use dynamic imports for settings client pages (#19461) 2025-02-21 13:27:27 -07:00
Vijay 22104f8d91 enable_pip_ui in dailyvideo (#19423) 2025-02-21 17:47:00 +00:00
Alex van Andel 26d2decea4 Revert "feat: display alert when leaving/reloading booking page (#18932)"
This reverts commit b0921fe90a.
2025-02-21 17:09:07 +00:00
Benny Joo b6d8dc0bd6 wip (#19446) 2025-02-21 16:51:24 +00:00
178 changed files with 1141 additions and 952 deletions
+8
View File
@@ -0,0 +1,8 @@
undecided:
- calcom-monorepo
- "@calcom/app-store-cli"
- "@calcom/platform-constants"
- "@calcom/platform-enums"
- "@calcom/platform-types"
- "@calcom/platform-utils"
- "@calcom/prisma"
+3 -2
View File
@@ -2,6 +2,7 @@ API_KEY_PREFIX=cal_
DATABASE_URL="postgresql://postgres:@localhost:5450/calendso"
NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000
# Get it in console.cal.com
# Get CALCOM_LICENSE_KEY here: https://go.cal.com/get-license
CALCOM_LICENSE_KEY=""
NEXT_PUBLIC_API_V2_ROOT_URL=http://localhost:5555
NEXT_PUBLIC_API_V2_ROOT_URL=http://localhost:5555
-10
View File
@@ -190,16 +190,6 @@ We make sure of this by not using next in dev, but next build && next start, if
See <https://github.com/vercel/next.js/blob/canary/packages/next/server/dev/hot-reloader.ts#L79>. Here in dev mode OPTIONS method is hardcoded to return only GET and OPTIONS as allowed method. Running in Production mode would cause this file to be not used. This is hot-reloading logic only.
To remove this limitation, we need to ensure that on local endpoints are requested by swagger at /api/v1 and not /v1
## Hosted api through cal.com
> _❗ WARNING: This is still experimental and not fully implemented yet❗_
Go to console.cal.com
Add a deployment or go to an existing one.
Activate API or Admin addon
Provide your `DATABASE_URL`
Now you can call api.cal.com?key=CALCOM_LICENSE_KEY, which will connect to your own databaseUrl.
## How to deploy
We recommend deploying API in vercel.
-2
View File
@@ -9,8 +9,6 @@ const config: StorybookConfig = {
"../../../packages/ui/components/**/*.docs.mdx",
"../../../packages/features/**/*.stories.@(js|jsx|ts|tsx)",
"../../../packages/features/**/*.docs.mdx",
"../../../packages/atoms/**/*.stories.@(js|jsx|ts|tsx)",
"../../../packages/atoms/**/*.docs.mdx",
],
addons: [
+2 -1
View File
@@ -11,7 +11,8 @@ module.exports = {
* These styles will only be added in storybook, and will NOT
* end up in the final css bundle of apps using the components.
*/
"postcss-pseudo-companion-classes": {
[require.resolve("postcss-pseudo-companion-classes")]: {
prefix: "sb-pseudo--",
prefix: "sb-pseudo--",
// We have to keep a restrictTo list here, because otherwise
// this library will have issues processing tailwind's \: prefixed classes
@@ -0,0 +1,25 @@
import { cookies, headers } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import PageWrapper from "@components/PageWrapperAppDir";
import { ssrInit } from "@server/lib/ssr";
export default async function BookingPageWrapperLayout({ children }: { children: React.ReactNode }) {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;
const context = buildLegacyCtx(h, cookies(), {}, {});
const ssr = await ssrInit(context);
return (
<PageWrapper
isBookingPage={true}
requiresLicense={false}
nonce={nonce}
themeBasis={null}
dehydratedState={ssr.dehydrate()}>
{children}
</PageWrapper>
);
}
@@ -1,7 +1,6 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps } from "app/_types";
import { generateMeetingMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
@@ -56,11 +55,12 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
};
};
const Page = async (props: OrgTypePageProps) => {
const ServerPage = async ({ params, searchParams }: PageProps) => {
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
if ((props as TeamTypePageProps)?.teamId) {
return <TeamTypePage {...(props as TeamTypePageProps)} />;
}
return <UserTypePage {...(props as UserTypePageProps)} />;
};
export default WithLayout({ getLayout: null, getData, ServerPage: Page, isBookingPage: true });
export default ServerPage;
@@ -1,7 +1,6 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps } from "app/_types";
import { generateMeetingMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
@@ -78,11 +77,12 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
}
};
const Page = async (props: OrgPageProps) => {
const ServerPage = async ({ params, searchParams }: PageProps) => {
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
if ((props as TeamPageProps)?.team) {
return <TeamPage {...(props as TeamPageProps)} />;
}
return <UserPage {...(props as UserPageProps)} />;
};
export default WithLayout({ getLayout: null, getData, ServerPage: Page, isBookingPage: true });
export default ServerPage;
@@ -1,7 +1,6 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps as _PageProps } from "app/_types";
import { generateMeetingMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { headers, cookies } from "next/headers";
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
@@ -50,4 +49,10 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
};
const getData = withAppDirSsr<Props>(getServerSideProps);
export default WithLayout({ getData, Page, isBookingPage: true })<"P">;
const ServerPage = async ({ params, searchParams }: _PageProps) => {
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
return <Page {...props} />;
};
export default ServerPage;
@@ -0,0 +1,4 @@
import Page from "app/(booking-page-wrapper)/team/[slug]/page";
export { generateMetadata } from "app/(booking-page-wrapper)/team/[slug]/page";
export default Page;
@@ -0,0 +1,4 @@
import Page from "app/(booking-page-wrapper)/team/[slug]/[type]/page";
export { generateMetadata } from "app/(booking-page-wrapper)/team/[slug]/[type]/page";
export default Page;
@@ -0,0 +1,4 @@
import Page from "app/(booking-page-wrapper)/team/[slug]/page";
export { generateMetadata } from "app/(booking-page-wrapper)/team/[slug]/page";
export default Page;
@@ -1,7 +1,6 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps } from "app/_types";
import { generateMeetingMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
@@ -51,9 +50,8 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const getData = withAppDirSsr<LegacyPageProps>(getServerSideProps);
export default WithLayout({
Page: LegacyPage,
getData,
getLayout: null,
isBookingPage: true,
})<"P">;
const ServerPage = async ({ params, searchParams }: PageProps) => {
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
return <LegacyPage {...props} />;
};
export default ServerPage;
@@ -1,7 +1,6 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps as _PageProps } from "app/_types";
import { generateMeetingMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
@@ -45,9 +44,8 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
const getData = withAppDirSsr<PageProps>(getServerSideProps);
export default WithLayout({
Page: LegacyPage,
getData,
getLayout: null,
isBookingPage: true,
})<"P">;
const ServerPage = async ({ params, searchParams }: _PageProps) => {
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
return <LegacyPage {...props} />;
};
export default ServerPage;
@@ -9,6 +9,7 @@ import { ssrInit } from "@server/lib/ssr";
export default async function PageWrapperLayout({ children }: { children: React.ReactNode }) {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;
const context = buildLegacyCtx(headers(), cookies(), {}, {});
const ssr = await ssrInit(context);
@@ -1,4 +1,3 @@
import dynamic from "next/dynamic";
import { cookies, headers } from "next/headers";
import React from "react";
@@ -8,10 +7,7 @@ import { buildLegacyRequest } from "@lib/buildLegacyCtx";
import SettingsLayoutAppDir from "../(settings-layout)/layout";
import type { AdminLayoutProps } from "./AdminLayoutAppDirClient";
const AdminLayoutAppDirClient = dynamic(() => import("./AdminLayoutAppDirClient"), {
ssr: false,
});
import AdminLayoutAppDirClient from "./AdminLayoutAppDirClient";
type AdminLayoutAppDirProps = Omit<AdminLayoutProps, "userRole">;
@@ -1,4 +1,3 @@
import dynamic from "next/dynamic";
import { cookies, headers } from "next/headers";
import React from "react";
@@ -8,10 +7,7 @@ import { OrganizationRepository } from "@calcom/lib/server/repository/organizati
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
import type { SettingsLayoutProps } from "./SettingsLayoutAppDirClient";
const SettingsLayoutAppDirClient = dynamic(() => import("./SettingsLayoutAppDirClient"), {
ssr: false,
});
import SettingsLayoutAppDirClient from "./SettingsLayoutAppDirClient";
type SettingsLayoutAppDirProps = Omit<SettingsLayoutProps, "currentOrg" | "otherTeams">;
-31
View File
@@ -1,31 +0,0 @@
import type { GetStaticProps, GetStaticPropsContext } from "next";
import { unstable_cache } from "next/cache";
import { notFound, redirect } from "next/navigation";
export const withAppDirSsg =
<T extends Record<string, any>>(getStaticProps: GetStaticProps<T>, routePath: string) =>
async (context: GetStaticPropsContext) => {
const cacheKey = JSON.stringify({
route: routePath,
params: context.params || {},
});
const getCachedProps = unstable_cache(async () => {
const ssgResponse = await getStaticProps(context);
if ("redirect" in ssgResponse) {
redirect(ssgResponse.redirect.destination);
}
if ("notFound" in ssgResponse) {
notFound();
}
return {
...ssgResponse.props,
...("trpcState" in ssgResponse.props && { dehydratedState: ssgResponse.props.trpcState }),
};
}, [`ssg-${cacheKey}`]);
return getCachedProps();
};
@@ -1,10 +0,0 @@
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";
import { getServerSideProps } from "@server/lib/[user]/[type]/getServerSideProps";
import LegacyPage, { type PageProps } from "~/users/views/users-type-public-view";
const getEmbedData = withEmbedSsrAppDir<PageProps>(getServerSideProps);
export default WithLayout({ getLayout: null, getData: getEmbedData, Page: LegacyPage })<"P">;
-11
View File
@@ -1,11 +0,0 @@
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";
import { getServerSideProps } from "@server/lib/[user]/getServerSideProps";
import type { PageProps as UserPageProps } from "~/users/views/users-public-view";
import LegacyPage from "~/users/views/users-public-view";
const getEmbedData = withEmbedSsrAppDir<UserPageProps>(getServerSideProps);
export default WithLayout({ getLayout: null, getData: getEmbedData, Page: LegacyPage })<"P">;
@@ -1,10 +0,0 @@
import Page from "@pages/org/[orgSlug]/[user]/[type]/embed";
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";
import type { OrgTypePageProps } from "app/org/[orgSlug]/[user]/[type]/page";
import { getServerSideProps } from "@lib/org/[orgSlug]/[user]/[type]/getServerSideProps";
const getEmbedData = withEmbedSsrAppDir<OrgTypePageProps>(getServerSideProps);
export default WithLayout({ getLayout: null, getData: getEmbedData, isBookingPage: true, Page });
@@ -1,21 +0,0 @@
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";
import type { OrgPageProps } from "app/org/[orgSlug]/[user]/page";
import { getServerSideProps } from "@lib/org/[orgSlug]/[user]/getServerSideProps";
import type { PageProps as TeamPageProps } from "~/team/team-view";
import TeamPage from "~/team/team-view";
import UserPage from "~/users/views/users-public-view";
import type { PageProps as UserPageProps } from "~/users/views/users-public-view";
const getEmbedData = withEmbedSsrAppDir<OrgPageProps>(getServerSideProps);
const Page = async (props: OrgPageProps) => {
if ((props as TeamPageProps)?.team) {
return <TeamPage {...(props as TeamPageProps)} />;
}
return <UserPage {...(props as UserPageProps)} />;
};
export default WithLayout({ getLayout: null, getData: getEmbedData, isBookingPage: true, ServerPage: Page });
@@ -1,16 +0,0 @@
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";
import { getServerSideProps } from "@lib/team/[slug]/getServerSideProps";
import type { PageProps } from "~/team/team-view";
import TeamPage from "~/team/team-view";
const getEmbedData = withEmbedSsrAppDir<PageProps>(getServerSideProps);
export default WithLayout({
Page: TeamPage,
getData: getEmbedData,
getLayout: null,
isBookingPage: true,
})<"P">;
-61
View File
@@ -1,61 +0,0 @@
import type { LayoutProps, PageProps } from "app/_types";
import { type GetServerSidePropsContext } from "next";
import { cookies, headers } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import PageWrapper from "@components/PageWrapperAppDir";
type WithLayoutParams<T extends Record<string, any>> = {
getLayout?: ((page: React.ReactElement) => React.ReactNode) | null;
getServerLayout?: (page: React.ReactElement) => Promise<React.ReactNode | null>;
Page?: (props: T) => React.ReactElement | null;
ServerPage?: (props: T) => Promise<React.ReactElement> | null;
getData?: (arg: GetServerSidePropsContext) => Promise<T | undefined>;
isBookingPage?: boolean;
requiresLicense?: boolean;
};
export function WithLayout<T extends Record<string, any>>({
getLayout,
getServerLayout,
getData,
ServerPage,
Page,
isBookingPage,
requiresLicense,
}: WithLayoutParams<T>) {
// eslint-disable-next-line react/display-name
return async <P extends "P" | "L">(p: P extends "P" ? PageProps : LayoutProps) => {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;
let props = {} as T;
if ("searchParams" in p && getData) {
props = (await getData(buildLegacyCtx(h, cookies(), p.params, p.searchParams))) ?? ({} as T);
}
// `p.children` exists only for layout.tsx files
const childrenFromLayoutFile = "children" in p ? p.children : null;
const page = ServerPage ? (
await ServerPage({ ...props, ...p })
) : Page ? (
<Page {...props} />
) : (
childrenFromLayoutFile
);
const pageWithServerLayout = page ? (getServerLayout ? await getServerLayout(page) : page) : null;
return (
<PageWrapper
getLayout={getLayout}
requiresLicense={requiresLicense || !!(Page && "requiresLicense" in Page && Page.requiresLicense)}
nonce={nonce}
themeBasis={null}
isBookingPage={isBookingPage || !!(Page && "isBookingPage" in Page && Page.isBookingPage)}
{...props}>
{pageWithServerLayout}
</PageWrapper>
);
};
}
-4
View File
@@ -1,4 +0,0 @@
import Page from "app/team/[slug]/page";
export { generateMetadata } from "app/team/[slug]/page";
export default Page;
@@ -1,4 +0,0 @@
import Page from "app/team/[slug]/[type]/page";
export { generateMetadata } from "app/team/[slug]/[type]/page";
export default Page;
@@ -1,4 +0,0 @@
import Page from "app/team/[slug]/page";
export { generateMetadata } from "app/team/[slug]/page";
export default Page;
@@ -93,7 +93,7 @@ const EnterpriseLicense = (
<Button
className="w-full justify-center text-lg"
EndIcon="external-link"
href="https://console.cal.com"
href="https://go.cal.com/get-license"
target="_blank">
{t("purchase_license")}
</Button>
@@ -198,7 +198,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
<span
className={classNames(
isInputUsernamePremium ? "border border-orange-400 " : "",
"border-default bg-muted text-subtle hidden h-9 items-center rounded-l-md border border-r-0 px-3 text-sm md:inline-flex"
"border-default bg-muted text-subtle hidden h-8 items-center rounded-l-md border border-r-0 px-3 text-sm md:inline-flex"
)}>
{process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")}/
</span>
@@ -212,7 +212,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
autoCorrect="none"
disabled={disabled}
className={classNames(
"border-l-1 my-0 rounded-md rounded-l-none font-sans text-sm leading-4 focus:!ring-0",
"border-l-1 my-0 rounded-md font-sans text-sm leading-4 focus:!ring-0 sm:rounded-l-none",
isInputUsernamePremium
? "border border-orange-400 focus:border focus:border-orange-400"
: "border focus:border",
+1 -1
View File
@@ -287,7 +287,7 @@ const AppProviders = (props: PageWrapperProps) => {
RemainingProviders
);
if (isBookingPage) {
if (props.isBookingPage || isBookingPage) {
return Hydrated;
}
+5 -1
View File
@@ -16,7 +16,7 @@ const safeGet = async <T = any>(key: string): Promise<T | undefined> => {
}
};
export const POST_METHODS_ALLOWED_API_ROUTES = ["/api/auth/signup", "/api/trpc"];
export const POST_METHODS_ALLOWED_API_ROUTES = ["/api/"]; // trailing slash in "/api/" is actually important to block edge cases like `/api.php`
// Some app routes are allowed because "revalidatePath()" is used to revalidate the cache for them
export const POST_METHODS_ALLOWED_APP_ROUTES = ["/settings/my-account/general"];
@@ -194,6 +194,10 @@ export const config = {
"/booking/:path*",
"/payment/:path*",
"/routing-forms/:path*",
"/team/:path*",
"/org/:path*",
"/:user/:type/",
"/:user/",
],
};
@@ -3,7 +3,7 @@
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import type { z } from "zod";
import checkForMultiplePaymentApps from "@calcom/app-store/_utils/payments/checkForMultiplePaymentApps";
@@ -4,7 +4,7 @@ import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import React from "react";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
@@ -102,7 +102,7 @@ type RowData =
};
function BookingsContent({ status }: BookingsProps) {
const { data: filterQuery, pushItemToKey } = useFilterQuery();
const { data: filterQuery } = useFilterQuery();
const { t } = useLocale();
const user = useMeQuery().data;
@@ -110,13 +110,6 @@ function BookingsContent({ status }: BookingsProps) {
const tableContainerRef = useRef<HTMLDivElement>(null);
useProperHeightForMobile(tableContainerRef);
useEffect(() => {
if (user?.isTeamAdminOrOwner && !filterQuery.userIds?.length) {
setIsFiltersVisible(true);
pushItemToKey("userIds", user?.id);
}
}, [user, filterQuery.status]);
const query = trpc.viewer.bookings.get.useInfiniteQuery(
{
limit: 10,
@@ -7,8 +7,8 @@ import { useSession } from "next-auth/react";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { Fragment, useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import { RRule } from "rrule";
import { Toaster } from "sonner";
import { z } from "zod";
import BookingPageTagManager from "@calcom/app-store/BookingPageTagManager";
@@ -4,7 +4,7 @@ import { signOut } from "next-auth/react";
import type { TFunction } from "next-i18next";
import { usePathname, useRouter } from "next/navigation";
import { Suspense } from "react";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { z } from "zod";
import { classNames } from "@calcom/lib";
+1 -1
View File
@@ -11,7 +11,7 @@ import Script from "next/script";
import { useState, useEffect } from "react";
import type { SubmitHandler } from "react-hook-form";
import { useForm, useFormContext } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { z } from "zod";
import getStripe from "@calcom/app-store/stripepayment/lib/client";
-2
View File
@@ -240,6 +240,4 @@ function TeamPage({ team, considerUnpublished, isValidOrgDomain }: PageProps) {
);
}
TeamPage.isBookingPage = true;
export default TeamPage;
@@ -3,7 +3,7 @@
import classNames from "classnames";
import type { InferGetServerSidePropsType } from "next";
import Link from "next/link";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import {
sdkActionManager,
@@ -146,5 +146,5 @@ export function UserPage(props: PageProps) {
</>
);
}
UserPage.isBookingPage = true;
export default UserPage;
@@ -48,6 +48,4 @@ function Type({ slug, user, isEmbed, booking, isBrandingHidden, eventData, orgBa
);
}
Type.isBookingPage = true;
export default Type;
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@calcom/web",
"version": "5.0.5",
"version": "5.0.6",
"private": true,
"scripts": {
"analyze": "ANALYZE=true next build",
@@ -122,7 +122,6 @@
"react-dom": "^18.2.0",
"react-easy-crop": "^3.5.2",
"react-hook-form": "^7.43.3",
"react-hot-toast": "^2.3.0",
"react-intl": "^5.25.1",
"react-live-chat-loader": "^2.8.1",
"react-multi-email": "^0.5.3",
@@ -139,6 +138,7 @@
"sanitize-html": "^2.10.0",
"schema-dts": "^1.1.0",
"short-uuid": "^4.2.0",
"sonner": "^1.7.4",
"stripe": "^9.16.0",
"superjson": "1.9.1",
"tailwindcss-radix": "^2.6.0",
+10 -6
View File
@@ -3,22 +3,26 @@ const { nextJsOrgRewriteConfig } = require("./getNextjsOrgRewriteConfig");
/** Needed to rewrite public booking page, gets all static pages but [user] */
// Pages found here are excluded from redirects in beforeFiles in next.config.js
let pages = (exports.pages = glob
.sync("{pages,app,app/(use-page-wrapper),app/(use-page-wrapper)/(main-nav)}/**/[^_]*.{tsx,js,ts}", {
cwd: __dirname,
})
.sync(
"{pages,app,app/(booking-page-wrapper),app/(use-page-wrapper),app/(use-page-wrapper)/(main-nav)}/**/[^_]*.{tsx,js,ts}",
{
cwd: __dirname,
}
)
.map((filename) =>
filename
.replace(/^(app\/\(use-page-wrapper\)\/\(main-nav\)|app\/\(use-page-wrapper\)|pages|app)\//, "")
.replace(
/^(app\/\(use-page-wrapper\)\/\(main-nav\)|app\/\(use-page-wrapper\)|app\/\(booking-page-wrapper\)|pages|app)\//,
""
)
.replace(/(\.tsx|\.js|\.ts)/, "")
.replace(/\/.*/, "")
)
// "/future" is a temporary directory for incremental migration to App Router
.filter(
(v, i, self) =>
self.indexOf(v) === i &&
![
"[user]",
"future",
"_trpc",
"layout",
"layoutHOC",
+66 -31
View File
@@ -1,12 +1,13 @@
import { expect } from "@playwright/test";
import { prisma } from "@calcom/prisma";
import prisma from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/client";
import { MembershipRole } from "@calcom/prisma/enums";
import { createTeamEventType } from "./fixtures/users";
import type { Fixtures } from "./lib/fixtures";
import { test } from "./lib/fixtures";
import { localize, setupManagedEvent } from "./lib/testUtils";
import { setupManagedEvent } from "./lib/testUtils";
test.afterEach(({ users }) => users.deleteAll());
@@ -209,18 +210,22 @@ test.describe("Bookings", () => {
webhookReceiver.close();
});
});
test("Admin bookings filtered by default", async ({ page, users, bookings }) => {
const t = await localize("en");
test("People filter includes bookings where filtered person is attendee", async ({
page,
users,
bookings,
}) => {
const firstUser = await users.create(
{ name: "First", email: "first@cal.com" },
{ name: "First" },
{
hasTeam: true,
teamRole: MembershipRole.ADMIN,
}
);
const teamId = (await firstUser.getFirstTeamMembership()).teamId;
const secondUser = await users.create({ name: "Second", email: "second@cal.com" });
const thirdUser = await users.create({ name: "Third", email: "third@cal.com" });
const secondUser = await users.create({ name: "Second" });
const thirdUser = await users.create({ name: "Third" });
// Add teammates to the team
await prisma.membership.createMany({
data: [
@@ -238,64 +243,94 @@ test.describe("Bookings", () => {
},
],
});
const teamEvent = await createTeamEventType(
{ id: firstUser.id },
{ id: teamId },
{ teamEventSlug: "team-event-slug" }
);
//Create a single booking for FirstUser(admin)
const firstUserBookingFixture = await createBooking({
title: "FirstUser as Organizer Meeting",
//Create a TeamEventType booking where ThirdUser is attendee
const thirdUserAttendeeTeamEventBookingFixture = await createBooking({
title: "ThirdUser is Attendee for TeamEvent",
bookingsFixture: bookings,
relativeDate: 6,
organizer: firstUser,
organizerEventType: teamEvent,
attendees: [{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" }],
});
const thirdUserAttendeeTeamEvent = await thirdUserAttendeeTeamEventBookingFixture.self();
//Create a IndividualEventType booking where ThirdUser,SecondUser are attendees and FirstUser is organizer
const thirdUserAttendeeIndividualBookingFixture = await createBooking({
title: "ThirdUser is Attendee and FirstUser is Organizer",
bookingsFixture: bookings,
relativeDate: 3,
organizer: firstUser,
organizerEventType: firstUser.eventTypes[0],
attendees: [
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
{ name: "Second", email: secondUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
],
});
const firstUserBooking = await firstUserBookingFixture.self();
const thirdUserAttendeeIndividualBooking = await thirdUserAttendeeIndividualBookingFixture.self();
//Create 2 bookings for SecondUser
await createBooking({
title: "SecondUser as Organizer Meeting 1",
//Create a IndividualEventType booking where ThirdUser is organizer and FirstUser,SecondUser are attendees
const thirdUserOrganizerBookingFixture = await createBooking({
title: "ThirdUser is Organizer and FirstUser is Attendee",
bookingsFixture: bookings,
organizer: secondUser,
organizer: thirdUser,
relativeDate: 2,
organizerEventType: secondUser.eventTypes[0],
organizerEventType: thirdUser.eventTypes[0],
attendees: [
{ name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
{ name: "Second", email: secondUser.email, timeZone: "Europe/Berlin" },
],
});
const thirdUserOrganizerBooking = await thirdUserOrganizerBookingFixture.self();
//Create a booking where FirstUser is organizer and SecondUser is attendee
await createBooking({
title: "SecondUser as Organizer Meeting 2",
title: "FirstUser is Organizer and SecondUser is Attendee",
bookingsFixture: bookings,
organizer: secondUser,
organizer: firstUser,
relativeDate: 4,
organizerEventType: secondUser.eventTypes[0],
attendees: [
{ name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
],
organizerEventType: firstUser.eventTypes[0],
attendees: [{ name: "Second", email: secondUser.email, timeZone: "Europe/Berlin" }],
});
//admin login
//Select 'ThirdUser' in people filter
await firstUser.apiLogin();
await Promise.all([
page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
page.goto(`/bookings/upcoming`),
page.waitForTimeout(10000),
page.waitForURL(`**\/upcoming?status=upcoming&userIds=${firstUser.id}`),
page.goto(`/bookings/upcoming?status=upcoming&userIds=${thirdUser.id}`),
]);
//expect only 1 booking (of admin) to be shown in list due to default filtering for admin
//expect only 3 bookings (out of 4 total) to be shown in list.
//where ThirdUser is either organizer or attendee
const upcomingBookingsTable = page.locator('[data-testid="upcoming-bookings"]');
const bookingListItems = upcomingBookingsTable.locator('[data-testid="booking-item"]');
const bookingListCount = await bookingListItems.count();
expect(bookingListCount).toBe(1);
expect(bookingListCount).toBe(3);
//verify with the booking titles
const firstUpcomingBooking = bookingListItems.nth(0);
await expect(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
firstUpcomingBooking.locator(`text=${firstUserBooking!.title}`)
firstUpcomingBooking.locator(`text=${thirdUserOrganizerBooking!.title}`)
).toBeVisible();
const secondUpcomingBooking = bookingListItems.nth(1);
await expect(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
secondUpcomingBooking.locator(`text=${thirdUserAttendeeIndividualBooking!.title}`)
).toBeVisible();
const thirdUpcomingBooking = bookingListItems.nth(2);
await expect(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
thirdUpcomingBooking.locator(`text=${thirdUserAttendeeTeamEvent!.title}`)
).toBeVisible();
});
});
+1 -1
View File
@@ -86,7 +86,7 @@ const createTeamWorkflow = async (user: { id: number }, team: { id: number }) =>
});
};
const createTeamEventType = async (
export const createTeamEventType = async (
user: { id: number },
team: { id: number },
scenario?: {
@@ -177,7 +177,7 @@ test.describe("Organization", () => {
await page.getByTestId("new-member-button").click();
await page.locator('[placeholder="email\\@example\\.com"]').fill(adminEmail);
await page.getByTestId("invite-new-member-button").click();
await expect(page.locator(`li:has-text("${adminEmail}")`)).toBeVisible();
await expect(page.getByTestId("pending-member-item").filter({ hasText: adminEmail })).toBeVisible();
// TODO: Check if invited admin received the invitation email
// await expectInvitationEmailToBeReceived(
// page,
@@ -344,7 +344,7 @@ test.describe("Organization", () => {
await page.getByTestId("new-member-button").click();
await page.locator('[placeholder="email\\@example\\.com"]').fill(adminEmail);
await page.getByTestId("invite-new-member-button").click();
await expect(page.locator(`li:has-text("${adminEmail}")`)).toBeVisible();
await expect(page.getByTestId("pending-member-item").filter({ hasText: adminEmail })).toBeVisible();
// TODO: Check if invited admin received the invitation email
// await expectInvitationEmailToBeReceived(
// page,
@@ -476,7 +476,7 @@ test.describe("Organization", () => {
await page.getByTestId("new-member-button").click();
await page.locator('[placeholder="email\\@example\\.com"]').fill(adminEmail);
await page.getByTestId("invite-new-member-button").click();
await expect(page.locator(`li:has-text("${adminEmail}")`)).toBeVisible();
await expect(page.getByTestId("pending-member-item").filter({ hasText: adminEmail })).toBeVisible();
// TODO: Check if invited admin received the invitation email
// await expectInvitationEmailToBeReceived(
// page,
@@ -45,7 +45,7 @@ test.describe("Teams", () => {
await page.getByTestId("new-member-button").click();
await page.locator('[placeholder="email\\@example\\.com"]').fill(inviteeEmail);
await page.getByTestId("invite-new-member-button").click();
await expect(page.locator(`li:has-text("${inviteeEmail}")`)).toBeVisible();
await expect(page.getByTestId("pending-member-item").filter({ hasText: inviteeEmail })).toBeVisible();
// locator.count() does not await for the expected number of elements
// https://github.com/microsoft/playwright/issues/14278
@@ -1987,7 +1987,7 @@
"a_routing_form": "نموذج توجيه",
"form_description_placeholder": "وصف النموذج",
"keep_me_connected_with_form": "ابقني متصلاً بالنموذج",
"fields_in_form_duplicated": "أي تغييرات في جهاز التوجيه والحقول الخاصة بالنموذج المكرر، ستنعكس في النسخة المكررة.",
"fields_in_form_duplicated": "أي تغييرات تتم على الموجه أو حقول النموذج الذي يتم نسخه ستنعكس في النسخة المكررة. ومع ذلك، فإن حذف حقل لن يؤدي إلى إزالته من النسخة المكررة.",
"form_deleted": "تم حذف النموذج",
"delete_form": "هل أنت متأكد من أنك تريد حذف هذا القالب؟",
"delete_form_action": "نعم، حذف النموذج",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Yönləndirmə Forması",
"form_description_placeholder": "Formanın təsviri",
"keep_me_connected_with_form": "Məni forma ilə əlaqədə saxla",
"fields_in_form_duplicated": "Formanın Router və Sahələrində edilən hər hansı dəyişikliklər dublikatda əks olunacaq.",
"fields_in_form_duplicated": "Dublikat edilən formanın marşrutlayıcısında və ya sahələrində edilən hər hansı dəyişiklik dublikatda öz əksini tapacaq. Lakin, bir sahənin silinməsi onu dublikatdan silməyəcək.",
"form_deleted": "Forma silindi",
"delete_form": "Bu formu silmək istədiyinizə əminsinizmi?",
"delete_form_action": "Bəli, Formu sil",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Форма за маршрутизиране",
"form_description_placeholder": "Описание на формата",
"keep_me_connected_with_form": "Поддържай ме свързан с формата",
"fields_in_form_duplicated": "Всички промени в маршрутизатора и полетата на дублираната форма ще се отразят в дубликата.",
"fields_in_form_duplicated": "Всички промени, направени в маршрутизатора или полетата на формуляра, който се дублира, ще бъдат отразени в дубликата. Въпреки това, изтриването на поле няма да го премахне от дубликата.",
"form_deleted": "Формата е изтрита",
"delete_form": "Сигурни ли сте, че искате да изтриете този формуляр?",
"delete_form_action": "Да, изтрий формуляра",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un formulari de redirecció",
"form_description_placeholder": "Descripció del formulari",
"keep_me_connected_with_form": "Mantén-me connectat amb el formulari",
"fields_in_form_duplicated": "Qualsevol canvi en el router i els camps del formulari que s'està duplicant es reflectirà en el duplicat.",
"fields_in_form_duplicated": "Qualsevol canvi fet al router o als camps del formulari que s'està duplicant es reflectirà en el duplicat. No obstant això, eliminar un camp no el suprimirà del duplicat.",
"form_deleted": "Formulari eliminat",
"delete_form": "Estàs segur que vols eliminar aquest formulari?",
"delete_form_action": "Sí, elimina el formulari",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Směrovací formulář",
"form_description_placeholder": "Popis formuláře",
"keep_me_connected_with_form": "Udržujte se mnou spojení pomocí formuláře",
"fields_in_form_duplicated": "Veškeré změny ve směrování a polích duplikovaného formuláře se promítnou v duplicitě.",
"fields_in_form_duplicated": "Jakékoli změny provedené ve směrovači nebo polích duplikovaného formuláře se projeví v duplikátu. Smazání pole však neodstraní toto pole z duplikátu.",
"form_deleted": "Formulář odstraněn",
"delete_form": "Opravdu chcete tento formulář odstranit?",
"delete_form_action": "Ano, odstranit formulář",
@@ -1987,7 +1987,7 @@
"a_routing_form": "En Routing Formular",
"form_description_placeholder": "Formular Beskrivelse",
"keep_me_connected_with_form": "Hold mig i forbindelse med formularen",
"fields_in_form_duplicated": "Eventuelle ændringer i Router og Fields i den form, der er ved at blive duplikeret, vil afspejles i duplikatet.",
"fields_in_form_duplicated": "Eventuelle ændringer foretaget i routeren eller felterne i den formular, der duplikeres, vil blive afspejlet i duplikatet. Dog vil sletning af et felt ikke fjerne det fra duplikatet.",
"form_deleted": "Formular slettet",
"delete_form": "Slet Formular",
"delete_form_action": "Ja, slet formular",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Ein Weiterleitungsformular",
"form_description_placeholder": "Formularbeschreibung",
"keep_me_connected_with_form": "Verbindung mit dem Formular beibehalten",
"fields_in_form_duplicated": "Alle Änderungen an Weiterleitungsformularen und in den Feldern des Formulars, die dupliziert werden, werden auch im Duplikat wiedergegeben.",
"fields_in_form_duplicated": "Alle Änderungen, die am Router oder an den Feldern des zu duplizierenden Formulars vorgenommen werden, spiegeln sich im Duplikat wider. Das Löschen eines Feldes entfernt es jedoch nicht aus dem Duplikat.",
"form_deleted": "Formular gelöscht",
"delete_form": "Möchten Sie dieses Formular wirklich löschen?",
"delete_form_action": "Ja, Formular löschen",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Μια φόρμα δρομολόγησης",
"form_description_placeholder": "Περιγραφή φόρμας",
"keep_me_connected_with_form": "Διατήρηση σύνδεσης με τη φόρμα",
"fields_in_form_duplicated": "Οποιεσδήποτε αλλαγές στη δρομολόγηση και τα πεδία της φόρμας που αντιγράφεται, θα αντικατοπτρίζονται στο αντίγραφο.",
"fields_in_form_duplicated": "Οποιεσδήποτε αλλαγές γίνουν στον δρομολογητή ή στα πεδία της φόρμας που αντιγράφεται θα αντικατοπτρίζονται στο αντίγραφο. Ωστόσο, η διαγραφή ενός πεδίου δεν θα το αφαιρέσει από το αντίγραφο.",
"form_deleted": "Η φόρμα διαγράφηκε",
"delete_form": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτή τη φόρμα;",
"delete_form_action": "Ναι, διαγραφή φόρμας",
@@ -56,7 +56,7 @@
"cancellation_reason": "Reason for cancellation (optional)",
"cancellation_reason_host": "Reason for cancellation",
"cancellation_reason_placeholder": "Why are you cancelling?",
"notify_attendee_cancellation_reason_warning":"Cancellation reason will be shared with guests",
"notify_attendee_cancellation_reason_warning": "Cancellation reason will be shared with guests",
"rejection_reason_placeholder": "Why are you rejecting?",
"rejection_reason": "Reason for rejecting",
"rejection_reason_title": "Reject the booking request?",
@@ -2672,7 +2672,7 @@
"x_marked_as_no_show": "{{x}} marked as no-show",
"x_unmarked_as_no_show": "{{x}} unmarked as no-show",
"team_select_info": "triggers for all team event types and all team members' personal event types",
"team_settings_description":"Manage settings for you team",
"team_settings_description": "Manage settings for you team",
"no_show_updated": "No-show status updated for attendees",
"email_copied": "Email copied",
"phone_number_copied": "Phone Number Copied",
@@ -2950,10 +2950,10 @@
"internal_booking_note": "Internal Note",
"internal_note_cancellation_reason": "Reason shared with customer (optional)",
"internal_booking_note_description": "This note will be visible to only members of your team",
"internal_note_presets":"Internal Cancelation Notes Presets",
"internal_note_presets_description" : "Create presets for internal notes that can be applied to bookings",
"internal_note_presets_updated_successfully" : "Internal note presets updated successfully",
"add_preset" : "Add Preset",
"internal_note_presets": "Internal Cancelation Notes Presets",
"internal_note_presets_description": "Create presets for internal notes that can be applied to bookings",
"internal_note_presets_updated_successfully": "Internal note presets updated successfully",
"add_preset": "Add Preset",
"authorize": "Authorize",
"next": "Next",
"hide": "Hide",
@@ -2961,5 +2961,6 @@
"desc": "Desc",
"verify_email": "Verify email",
"verify_email_change": "Verify email change",
"end_date_not_selected": "You didn't set an end date for your OOO",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un formulario de enrutamiento",
"form_description_placeholder": "Descripción del formulario",
"keep_me_connected_with_form": "Mantenerme conectado con el formulario",
"fields_in_form_duplicated": "Cualquier cambio en el enrutador y los campos del formulario duplicado se reflejará en el duplicado.",
"fields_in_form_duplicated": "Cualquier cambio realizado en el enrutador o en los campos del formulario que se está duplicando se reflejará en el duplicado. Sin embargo, eliminar un campo no lo eliminará del duplicado.",
"form_deleted": "Formulario eliminado",
"delete_form": "¿Estás seguro de que quieres eliminar este formulario?",
"delete_form_action": "Sí, eliminar formulario",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un formulario de enrutamiento",
"form_description_placeholder": "Descripción del formulario",
"keep_me_connected_with_form": "Mantenerme conectado con el formulario",
"fields_in_form_duplicated": "Cualquier cambio en el enrutador y los campos del formulario que se está duplicando se reflejará en el duplicado.",
"fields_in_form_duplicated": "Cualquier cambio realizado en el enrutador o en los campos del formulario que se está duplicando se reflejará en el duplicado. Sin embargo, eliminar un campo no lo eliminará del duplicado.",
"form_deleted": "Formulario eliminado",
"delete_form": "¿Está seguro de que desea eliminar este formulario?",
"delete_form_action": "Sí, eliminar formulario",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Marsruutimisvorm",
"form_description_placeholder": "Vormi kirjeldus",
"keep_me_connected_with_form": "Hoidke mind vormiga ühenduses",
"fields_in_form_duplicated": "Kõik muudatused ruuteris ja dubleeritava vormi väljades kajastuvad duplikaadis.",
"fields_in_form_duplicated": "Kõik muudatused, mis tehakse dubleeritava vormi marsruuterile või väljadele, kajastuvad ka duplikaadis. Kuid välja kustutamine ei eemalda seda duplikaadist.",
"form_deleted": "Vorm kustutatud",
"delete_form": "Kas olete kindel, et soovite selle vormi kustutada?",
"delete_form_action": "Jah, kustuta vorm",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Bideratze-formulario bat",
"form_description_placeholder": "Formularioaren deskribapena",
"keep_me_connected_with_form": "Mantendu konektatuta formularioarekin",
"fields_in_form_duplicated": "Bikoiztutako formularioaren bideratzaile eta eremuetan egindako edozein aldaketa bikoiztuan islatuko da",
"fields_in_form_duplicated": "Bikoizten ari den inprimakiaren bideratzailean edo eremuetan egindako edozein aldaketa bikoiztuan islatuko da. Hala ere, eremu bat ezabatzeak ez du bikoiztutik kenduko.",
"form_deleted": "Formularioa ezabatuta",
"delete_form": "Ziur zaude formulario hau ezabatu nahi duzula?",
"delete_form_action": "Bai, ezabatu formularioa",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Reitityskaavake",
"form_description_placeholder": "Lomakkeen kuvaus",
"keep_me_connected_with_form": "Pidä minut yhteydessä lomakkeeseen",
"fields_in_form_duplicated": "Kaikki muutokset kopioitavan lomakkeen reitittimessä ja kentissä heijastuvat kopioituun versioon.",
"fields_in_form_duplicated": "Kaikki muutokset, jotka tehdään kopioitavan lomakkeen reitittimeen tai kenttiin, näkyvät myös kopiossa. Kentän poistaminen ei kuitenkaan poista sitä kopiosta.",
"form_deleted": "Lomake poistettu",
"delete_form": "Haluatko varmasti poistaa tämän lomakkeen?",
"delete_form_action": "Kyllä, poista lomake",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un formulaire de routage",
"form_description_placeholder": "Description du formulaire",
"keep_me_connected_with_form": "Rester connecté avec le formulaire",
"fields_in_form_duplicated": "Toute modification du routeur et des champs du formulaire dupliqué se répercutera dans la duplication.",
"fields_in_form_duplicated": "Toute modification apportée au routeur ou aux champs du formulaire en cours de duplication sera reflétée dans la copie. Cependant, la suppression d'un champ ne l'enlèvera pas de la copie.",
"form_deleted": "Formulaire supprimé",
"delete_form": "Voulez-vous vraiment supprimer ce formulaire ?",
"delete_form_action": "Oui, supprimer le formulaire",
@@ -1987,7 +1987,7 @@
"a_routing_form": "טופס ניתוב",
"form_description_placeholder": "תיאור הטופס",
"keep_me_connected_with_form": "שמור אותי מחובר לטופס",
"fields_in_form_duplicated": "כל שינוי בניתוב ובשדות הטופס שמשוכפל, ישפיעו על הטופס המשוכפל.",
"fields_in_form_duplicated": "כל שינוי שנעשה בנתב או בשדות של הטופס המשוכפל ישתקף בעותק. עם זאת, מחיקת שדה לא תסיר אותו מהעותק.",
"form_deleted": "הטופס נמחק",
"delete_form": "האם אתה בטוח שאתה רוצה למחוק את הטופס?",
"delete_form_action": "כן, מחק את הטופס",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Útválasztási űrlap",
"form_description_placeholder": "Űrlap leírása",
"keep_me_connected_with_form": "Tartson kapcsolatban az űrlappal",
"fields_in_form_duplicated": "A duplikált űrlap útválasztójában és mezőiben végzett bármilyen változás a másolatban is tükröződik.",
"fields_in_form_duplicated": "A másolandó űrlap útválasztójában vagy mezőiben végrehajtott változtatások megjelennek a másolatban. Azonban egy mező törlése nem távolítja el azt a másolatból.",
"form_deleted": "Űrlap törölve",
"delete_form": "Biztosan törli ezt az űrlapot?",
"delete_form_action": "Igen, törölje az űrlapot",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un modulo di instradamento",
"form_description_placeholder": "Descrizione modulo",
"keep_me_connected_with_form": "Mantieni la connessione con il modulo",
"fields_in_form_duplicated": "Le eventuali modifiche all'instradatore e ai campi del modulo da duplicare si rifletteranno nel duplicato.",
"fields_in_form_duplicated": "Qualsiasi modifica apportata al router o ai campi del modulo duplicato si rifletterà nella copia. Tuttavia, l'eliminazione di un campo non lo rimuoverà dalla copia.",
"form_deleted": "Modulo eliminato",
"delete_form": "Confermi l'eliminazione del modulo?",
"delete_form_action": "Sì, elimina modulo",
@@ -1987,7 +1987,7 @@
"a_routing_form": "ルーティングフォーム",
"form_description_placeholder": "フォームの説明",
"keep_me_connected_with_form": "フォームに接続したままにする",
"fields_in_form_duplicated": "ルーティングフォームとフォームフィールドの変更内容は複製され、複製に反映されます。",
"fields_in_form_duplicated": "複製されるフォームのルーターやフィールドに加えられた変更は、複製にも反映されます。ただし、フィールドを削除しても、複製からは削除されません。",
"form_deleted": "フォームを削除しました",
"delete_form": "このフォームを削除してもよろしいですか?",
"delete_form_action": "はい。フォームを削除します",
@@ -1987,7 +1987,7 @@
"a_routing_form": "បែបបទបញ្ជូន",
"form_description_placeholder": "ពិពណ៌នាបែបបទ",
"keep_me_connected_with_form": "រក្សាខ្ញុំឱ្យត្រូវបានភ្ជាប់ជាមួយទម្រង់",
"fields_in_form_duplicated": "ការផ្លាស់ប្តូរណាមួយនៅក្នុង Router និងវាលនៃទម្រង់ដែលត្រូវបានចម្លង នឹងត្រូវបានបង្ហាញនៅក្នុងចម្លង។",
"fields_in_form_duplicated": "រាល់ការផ្លាស់ប្តូរដែលបានធ្វើឡើងចំពោះ router ឬវាលនានានៃទម្រង់ដែលកំពុងត្រូវបានចម្លង នឹងត្រូវបានឆ្លុះបញ្ចាំងនៅក្នុងច្បាប់ចម្លង។ ទោះយ៉ាងណាក៏ដោយ ការលុបវាលមួយនឹងមិនលុបវាចេញពីច្បាប់ចម្លងនោះទេ។",
"form_deleted": "ទម្រង់ត្រូវបានលុប",
"delete_form": "តើអ្នកប្រាកដថាចង់លុបទម្រង់នេះមែនទេ?",
"delete_form_action": "បាទ/ចាស, លុបទម្រង់",
@@ -1987,7 +1987,7 @@
"a_routing_form": "라우팅 양식",
"form_description_placeholder": "양식 설명",
"keep_me_connected_with_form": "양식과 연결 상태 유지",
"fields_in_form_duplicated": "복제되는 양식에 있는 라우터 및 필드의 변경 사항은 복제본에 반영됩니다.",
"fields_in_form_duplicated": "복제되는 폼의 라우터나 필드에 대한 모든 변경 사항은 복제본에 반영됩니다. 그러나 필드를 삭제해도 복제본에서는 제거되지 않습니다.",
"form_deleted": "양식 삭제됨",
"delete_form": "이 양식을 삭제하시겠습니까?",
"delete_form_action": "예, 양식을 삭제하겠습니다",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Een routeringsformulier",
"form_description_placeholder": "Formulierbeschrijving",
"keep_me_connected_with_form": "Houd me verbonden met het formulier",
"fields_in_form_duplicated": "Wijzigingen in router en velden van het formulier die worden gedupliceerd, worden in het duplicaat verwerkt.",
"fields_in_form_duplicated": "Alle wijzigingen die worden aangebracht in de router of velden van het formulier dat wordt gedupliceerd, worden weergegeven in het duplicaat. Het verwijderen van een veld zal het echter niet uit het duplicaat verwijderen.",
"form_deleted": "Formulier verwijderd",
"delete_form": "Weet u zeker dat u dit formulier wilt verwijderen?",
"delete_form_action": "Ja, verwijder het formulier",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Et rutingsskjema",
"form_description_placeholder": "Skjema beskrivelse",
"keep_me_connected_with_form": "Hold meg tilkoblet med skjemaet",
"fields_in_form_duplicated": "Eventuelle endringer i Router og feltene i skjemaet som blir duplisert, vil gjenspeiles i duplikatet.",
"fields_in_form_duplicated": "Eventuelle endringer gjort i ruteren eller feltene i skjemaet som blir duplisert, vil gjenspeiles i duplikatet. Imidlertid vil sletting av et felt ikke fjerne det fra duplikatet.",
"form_deleted": "Skjema slettet",
"delete_form": "Er du sikker på at du vil slette dette skjemaet?",
"delete_form_action": "Ja, slett skjema",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Formularz przekierowania",
"form_description_placeholder": "Opis formularza",
"keep_me_connected_with_form": "Zachowaj połączenie z formularzem",
"fields_in_form_duplicated": "Duplikowanie zmian w formularzu przekierowania i jego polach zostanie odzwierciedlone w duplikacie.",
"fields_in_form_duplicated": "Wszelkie zmiany wprowadzone w routerze lub polach formularza, który jest duplikowany, zostaną odzwierciedlone w duplikacie. Jednak usunięcie pola nie spowoduje jego usunięcia z duplikatu.",
"form_deleted": "Formularz usunięty",
"delete_form": "Czy na pewno chcesz usunąć ten formularz?",
"delete_form_action": "Tak, usuń formularz",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Formulário de roteamento",
"form_description_placeholder": "Descrição do formulário",
"keep_me_connected_with_form": "Mantenha minha conexão com o formulário",
"fields_in_form_duplicated": "Qualquer alteração no formulário de roteamento e nos campos do formulário a ser duplicado afetará a cópia duplicada.",
"fields_in_form_duplicated": "Quaisquer alterações feitas no roteador ou nos campos do formulário que está sendo duplicado serão refletidas na cópia. No entanto, excluir um campo não o removerá da cópia.",
"form_deleted": "Formulário excluído",
"delete_form": "Tem certeza de que deseja excluir este formulário?",
"delete_form_action": "Sim, excluir formulário",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Um formulário de encaminhamento",
"form_description_placeholder": "Descrição do formulário",
"keep_me_connected_with_form": "Manter-me associado ao formulário",
"fields_in_form_duplicated": "Quaisquer alterações no Encaminhador e Campos do formulário que esteja a ser duplicado, irão refletir-se na duplicação.",
"fields_in_form_duplicated": "Quaisquer alterações feitas no roteador ou nos campos do formulário que está sendo duplicado serão refletidas na cópia. No entanto, excluir um campo não o removerá da cópia.",
"form_deleted": "Formulário eliminado",
"delete_form": "Eliminar formulário",
"delete_form_action": "Sim, eliminar formulário",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Un formular de parcurs",
"form_description_placeholder": "Descriere formular",
"keep_me_connected_with_form": "Vreau să primesc actualizări privind formularul",
"fields_in_form_duplicated": "Orice modificări aduse parcursului și câmpurilor din formularul duplicat se vor reflecta în duplicat.",
"fields_in_form_duplicated": "Orice modificări aduse rutei sau câmpurilor formularului care este duplicat vor fi reflectate în duplicat. Cu toate acestea, ștergerea unui câmp nu îl va elimina din duplicat.",
"form_deleted": "Formular șters",
"delete_form": "Sigur doriți să ștergeți acest formular?",
"delete_form_action": "Da, șterg formularul",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Форма маршрутизации",
"form_description_placeholder": "Описание формы",
"keep_me_connected_with_form": "Подключить меня к форме",
"fields_in_form_duplicated": "В случае дублирования формы любые изменения, вносимые в форму маршрутизации и ее поля, будут отражаться в копии.",
"fields_in_form_duplicated": "Любые изменения, внесенные в маршрутизатор или поля дублируемой формы, будут отражены в дубликате. Однако удаление поля не приведет к его удалению из дубликата.",
"form_deleted": "Форма удалена",
"delete_form": "Удалить эту форму?",
"delete_form_action": "Да, удалить форму",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Smerovací formulár",
"form_description_placeholder": "Popis formulára",
"keep_me_connected_with_form": "Zostať pripojený k formuláru",
"fields_in_form_duplicated": "Akékoľvek zmeny v smerovaní a poliach duplikovaného formulára sa prejavia v kópii.",
"fields_in_form_duplicated": "Akékoľvek zmeny vykonané v smerovači alebo poliach formulára, ktorý sa duplikuje, sa prejavia v duplikáte. Avšak odstránenie poľa neodstráni toto pole z duplikátu.",
"form_deleted": "Formulár bol vymazaný",
"delete_form": "Naozaj chcete vymazať tento formulár?",
"delete_form_action": "Áno, vymazať formulár",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Obrazac za usmeravanje",
"form_description_placeholder": "Opis formulara",
"keep_me_connected_with_form": "Držite me povezanim sa formularom",
"fields_in_form_duplicated": "Bilo koje promene rutera i polja u formularu koje su duplirane, pokazaće se u duplikatu.",
"fields_in_form_duplicated": "Sve promene napravljene na ruteru ili poljima formulara koji se duplicira biće odražene u duplikatu. Međutim, brisanje polja neće ga ukloniti iz duplikata.",
"form_deleted": "Formular je izbrisan",
"delete_form": "Da li ste sigurni da želite da izbrišete ovaj obrazac?",
"delete_form_action": "Da, izbriši formular",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Ett omdirigeringsformulär",
"form_description_placeholder": "Formulärbeskrivning",
"keep_me_connected_with_form": "Håll mig ansluten med formuläret",
"fields_in_form_duplicated": "Alla ändringar i omdirigering och fält i formuläret som dupliceras återspeglas i dubbletten.",
"fields_in_form_duplicated": "Alla ändringar som görs i routern eller fälten i formuläret som dupliceras kommer att återspeglas i kopian. Att radera ett fält kommer dock inte att ta bort det från kopian.",
"form_deleted": "Formulär borttaget",
"delete_form": "Vill du verkligen ta bort formuläret?",
"delete_form_action": "Ja, ta bort formulär",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Yönlendirme Formu",
"form_description_placeholder": "Form Açıklaması",
"keep_me_connected_with_form": "Formla bağlantımı sürdür",
"fields_in_form_duplicated": "Kopyalanan formun Yönlendirici ve Alanlarındaki tüm değişiklikler de kopyaya yansıtılır.",
"fields_in_form_duplicated": "Kopyalanan formun yönlendiricisinde veya alanlarında yapılan herhangi bir değişiklik, kopyada da yansıtılacaktır. Ancak, bir alanın silinmesi onu kopyadan kaldırmayacaktır.",
"form_deleted": "Form silindi",
"delete_form": "Bu formu silmek istediğinizden emin misiniz?",
"delete_form_action": "Evet, Formu sil",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Форма переспрямування",
"form_description_placeholder": "Опис форми",
"keep_me_connected_with_form": "Підтримувати зі мною зв’язок за допомогою форми",
"fields_in_form_duplicated": "Будь-які зміни, внесені у форму переспрямування і її поля, буде відображено в дублікаті цієї форми.",
"fields_in_form_duplicated": "Будь-які зміни, внесені до маршрутизатора або полів форми, що дублюється, відобразяться в дублікаті. Однак видалення поля не призведе до його видалення з дубліката.",
"form_deleted": "Форму видалено",
"delete_form": "Видалити цю форму?",
"delete_form_action": "Так, видалити форму",
@@ -1987,7 +1987,7 @@
"a_routing_form": "Một biểu mẫu định hướng",
"form_description_placeholder": "Mô tả biểu mẫu",
"keep_me_connected_with_form": "Duy trì trạng thái kết nối của tôi với biểu mẫu",
"fields_in_form_duplicated": "Mọi thay đổi trong Định hướng và Trường của biểu mẫu được sao chép đều sẽ được thể hiện trong bản sao.",
"fields_in_form_duplicated": "Bất kỳ thay đổi nào được thực hiện đối với bộ định tuyến hoặc các trường của biểu mẫu đang được sao chép sẽ được phản ánh trong bản sao. Tuy nhiên, việc xóa một trường sẽ không loại bỏ nó khỏi bản sao.",
"form_deleted": "Biểu mẫu đã xoá",
"delete_form": "Bạn có chắc bạn muốn xóa biểu mẫu này?",
"delete_form_action": "Có, xoá Biểu mẫu",
@@ -1987,7 +1987,7 @@
"a_routing_form": "途径表格",
"form_description_placeholder": "表格描述",
"keep_me_connected_with_form": "让我与表格保持连接",
"fields_in_form_duplicated": "所复制的途径表格本身和其字段的任何变化都会反映在副本中。",
"fields_in_form_duplicated": "对正在复制的表单的路由器或字段所做的任何更改都将反映在副本中。但是,删除字段不会将其从副本中移除。",
"form_deleted": "表格已删除",
"delete_form": "确定要删除此表格吗?",
"delete_form_action": "是,删除表格",
@@ -1987,7 +1987,7 @@
"a_routing_form": "引導表單",
"form_description_placeholder": "表單說明",
"keep_me_connected_with_form": "將我與此表單保持連結",
"fields_in_form_duplicated": "目前複製的引導表單和表單欄位如有任何變更,也會反映在複本中。",
"fields_in_form_duplicated": "對被複製的表單的路由或欄位所做的任何更改都會反映在複製品中。但是,刪除欄位不會從複製品中移除該欄位。",
"form_deleted": "已刪除表單",
"delete_form": "確定要刪除此表單嗎?",
"delete_form_action": "是,刪除表單",
+1 -1
View File
@@ -1984,7 +1984,7 @@ checksums:
a_routing_form: 0efb0603d4fa8a93c29815addfc5d7b7
form_description_placeholder: 4527874b1b330670c90509d544656e1c
keep_me_connected_with_form: 6c4e124876798fa31e95263cfedc6128
fields_in_form_duplicated: 141300cdba2154f3d7d4fa2e42560178
fields_in_form_duplicated: 21c9d77cb1153c092178b88f271e5626
form_deleted: 1826f64353f3707dd7ad3b4a5be622b7
delete_form: 1e565cab4c0ac382e5ea4f6f4b0148ef
delete_form_action: da5c9924cbeb6409a29e044f7a8577d9
+1 -1
View File
@@ -13,7 +13,7 @@ export type TDependencyData = {
}[];
/**
* Get App metdata either using dirName or slug
* Get App metadata either using dirName or slug
*/
export async function getAppWithMetadata(app: { dirName: string } | { slug: string }) {
let appMetadata: App | null;
+3 -3
View File
@@ -6,9 +6,9 @@
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "*",
"@getalby/lightning-tools": "^4.0.2",
"@getalby/sdk": "^2.4.0",
"@webbtc/webln-types": "^2.0.1",
"@getalby/lightning-tools": "^5.1.2",
"@getalby/sdk": "^4.0.0",
"@webbtc/webln-types": "^3.0.0",
"react-qr-code": "^2.0.12",
"svix": "^0.85.1"
},
@@ -2,7 +2,7 @@ import { auth, Client, webln } from "@getalby/sdk";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState, useCallback, useEffect } from "react";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import AppNotInstalledMessage from "@calcom/app-store/_components/AppNotInstalledMessage";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
@@ -1,7 +1,7 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -58,5 +58,5 @@ export const projectMutationHandler = async ({ ctx, input }: ProjectMutationHand
data: { key: { ...credentialKey, projectId: Number(projectId), scheduleId } },
});
return { messsage: "Updated project successfully" };
return { message: "Updated project successfully" };
};
@@ -1,7 +1,7 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Alert, Button, Form, TextField } from "@calcom/ui";
@@ -238,6 +238,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
enable_knocking: true,
enable_screenshare: true,
enable_chat: true,
enable_pip_ui: true,
exp: exp,
enable_recording: scalePlan === "true" && !!hasTeamPlan === true ? "cloud" : undefined,
enable_transcription_storage: !!hasTeamPlan,
@@ -264,6 +265,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
enable_knocking: true,
enable_screenshare: true,
enable_chat: true,
enable_pip_ui: true,
exp: exp,
enable_recording: isScalePlanTrue ? "cloud" : undefined,
start_video_off: true,
@@ -20,6 +20,7 @@ export const dailyReturnTypeSchema = z.object({
enable_knocking: z.boolean(),
enable_prejoin_ui: z.boolean(),
enable_transcription_storage: z.boolean().default(false),
enable_pip_ui: z.boolean(),
}),
});
@@ -147,7 +147,7 @@ export default class ExchangeCalendarService implements Calendar {
const externalCalendars: IntegrationCalendar[] = await this.listCalendars();
const calendarsToGetAppointmentsFrom = [];
for (let i = 0; i < selectedCalendars.length; i++) {
//Only select vaild calendars! (We get all all active calendars on the instance! even from different users!)
//Only select valid calendars! (We get all all active calendars on the instance! even from different users!)
for (let k = 0; k < externalCalendars.length; k++) {
if (selectedCalendars[i].externalId == externalCalendars[k].externalId) {
calendarsToGetAppointmentsFrom.push(selectedCalendars[i]);
@@ -1,7 +1,7 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Alert, Button, Form, TextField } from "@calcom/ui";
@@ -152,7 +152,7 @@ export default class ExchangeCalendarService implements Calendar {
const externalCalendars = await this.listCalendars();
const calendarsToGetAppointmentsFrom = [];
for (let i = 0; i < selectedCalendars.length; i++) {
//Only select vaild calendars! (We get all all active calendars on the instance! even from different users!)
//Only select valid calendars! (We get all all active calendars on the instance! even from different users!)
for (let k = 0; k < externalCalendars.length; k++) {
if (selectedCalendars[i].externalId == externalCalendars[k].externalId) {
calendarsToGetAppointmentsFrom.push(selectedCalendars[i]);
@@ -1,7 +1,7 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Alert, Button, Form, TextField } from "@calcom/ui";
@@ -2,7 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { Toaster } from "sonner";
import z from "zod";
import { emailSchema } from "@calcom/lib/emailSchema";
@@ -960,7 +960,7 @@ export default class GoogleCalendarService implements Calendar {
/** Expand the end date to the end of the month */
timeMax: getTimeMax(),
// Dont use eventTypeId in key because it can be used by any eventType
// The only reason we are building it per eventType is because there can be different groups of calendars to lookup the availablity for
// The only reason we are building it per eventType is because there can be different groups of calendars to lookup the availability for
items: selectedCalendars.map((sc) => ({ id: sc.externalId })),
};
const data = await this.fetchAvailability(parsedArgs);

Some files were not shown because too many files have changed in this diff Show More