Compare commits

..
67 Commits
Author SHA1 Message Date
Omar López 1722edbd36 chore: v4.4.9 (#16617)
release.yml / release (push) Canceled after 0s
2024-09-12 20:08:07 +00:00
Amit Sharma e68ab3b123 fix: prevent linking duplicate apple calendars (#16539)
* fix: prevent linking duplicate apple calendars

* fix: update when new password

* revert unnecessary change

* fix: use array.find
2024-09-13 01:08:38 +05:30
cf16cd3ed2 feat: Implement Dub.co for conversion tracking (#16165)
* FEAT: Implement Dub.co for conversion tracking

* add link creation, @vercel/functions

* use refer.cal.com/:username instead of go.cal.com/r/:username

* sale conversion tracking

* add copy referral link

* limit to IS_CALCOM only

* Update yarn.lock

* fix DubAnalytics

* use workaround for isNewUser

* pass req to getOptions

* Update next-auth-options.ts

* fix ts errors

* only show DubAnalytics outside EU

* add Dub Analytics to /signup

* use WEBSITE_URL instead

* on-demand generate links

* add migration

* add check for existing link + change fetch method to poast

* remove refer.cal.com from PoweredByCal

* limit DubAnalytics to /signup only

* simplify generate-referral-link

* restore yarn.lock

* add yarn with dub sdk in

* add yarn with dub sdk in

* yarn

* Update yarn.lock

---------

Co-authored-by: sean <sean@brydon.io>
Co-authored-by: Peer Richelsen <peer@cal.com>
2024-09-12 12:33:10 -07:00
Keith Williams f4bc7d2ea4 chore: Remove PR reviewed automation (#16615) 2024-09-13 03:25:10 +09:00
Amit Sharma f5f7242f02 fix: use current user email (#16577)
* fix: use current user email

* dont fallback to email param
2024-09-12 16:32:49 +00:00
8f5ac26bb1 fix: profile page flickering and refactor (#16555)
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2024-09-12 10:12:54 -04:00
Calcom BotandReplexica b983adb16a feat: update translations (#16603)
Co-authored-by: Replexica <support@replexica.com>
2024-09-12 14:06:47 +00:00
Abhijeet SinghandAmit Sharma 8ce018995a fix: (managed-event-booking): slug conflict handling (#16540)
* fix(managed-event-booking): slug conflict handling

* refactor logic

---------

Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
2024-09-12 10:05:05 -04:00
Maximilian FranzkeandAnik Dhabal Babu f11086e9f8 fix(ally): button (#16588)
The close button would actually need to be a `button` instead of a `span` HTML element to be both screenreader and keyboard user accessible, as well as having an accessible label.

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-12 13:29:27 +05:30
Rajiv SahalandMorgan 91f5d49cd4 feat: update v2 calendar services logic to handle multiple calendars (#16478)
* update calendar logic to handle multiple calendars

* add method to link calendar to credential

* remove logs

* update platform libraries

* update calendar logic to handle multiple calendars

* update credentials repository

* add selected calendars repository to destination calendars module

* add method to get user selected calendars and rename fn

* chore: PR feedback

* resolve merge conflicts

* fixup

* make sure we cover all edge cases for apple calendar

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2024-09-12 06:44:01 +00:00
Benny Joo 55e1e0fa3d chore: Remove passing optional prisma select prop to Repository classes (#16600) 2024-09-11 18:14:19 -07:00
4a59841b02 feat: booking with phone number (#14461)
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
2024-09-11 17:56:04 -07:00
Benny Joo 74a9f3c19e hotfix: availability/[schedule] (#16598) 2024-09-11 18:11:10 +00:00
Syed Ali Shahbaz 89250422ea fix: API V1 slots add explicit orgSlug null fallback (#16593)
* add explicit orgSlug null fallback

* do it in schema

* to nullish
2024-09-11 16:14:03 +00:00
Keith Williams 2f2f4dba60 chore: v4.4.8 (#16597)
release.yml / release (push) Canceled after 0s
2024-09-12 00:19:00 +09:00
Calcom BotandReplexica b292cafe7b feat: update translations (#16592)
Co-authored-by: Replexica <support@replexica.com>
2024-09-11 14:56:28 +00:00
Keith Williams 82053e0c7c perf: Include no shows in main status query (#16594)
* perf: Include no shows in main status query

* Removed the Promise.all call
2024-09-11 14:16:46 +00:00
Udit Takkar 860d173f0a feat: instant meeting browser notifcations (#16480)
* feat: instant meeting browser notifcations

* chore: support multiple notifications

* chore: save progress

* fix: add test notification and move file

* fix: type err

* chore: feedback improvements

* chore: undo DENY
2024-09-11 18:02:14 +04:00
Udit TakkarandSyed Ali Shahbaz 5bc0e1265d fix: use meeting id to get transcripts (#16320)
* fix: use meeting id to get transcripts

* chore

---------

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
2024-09-11 22:05:56 +09:00
Hariom Balhara e362c37ff3 fix: Location Change to Organizer Default Conferencing App (#16379)
* Fix

* Dont include test files

* Fix location change

* Self review fixes

* Add unit test

* Add more test

* Add a bookingScenario as well
2024-09-11 21:31:53 +09:00
4d53f327d9 feat: V2 API endpoint create phone call (#16528)
* refactor: V2 API endpoint create phone call

* fix: type err

* fix: type and build err

* chore: change default value

* chore: move it to another route

* test: for create phone call

* chore: undo constant

* chore: remove test

* fix: make begin_message optional

* chore: improvements

* chore: begin message

* chore: remove unused import

* chore: bump platform libraries with handleCreatePhoneCall

* chore: improvement

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Morgan Vernay <morgan@cal.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2024-09-11 11:11:54 +00:00
61f436be2a fix: wrong reschedule link for an org member for a booking on event outside the org (#15260)
* fix: wrong reschedule link

* test

* fix

* test

* test

* refactor: get org id of booking

* fix: redirect URL to handle movedToProfile username based on domain context

* Revert not needed changes

* Revert unnecessary changes now

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Hariom <hariombalhara@gmail.com>
2024-09-11 04:47:52 +00:00
Benny JooandUdit Takkar d1a0fc6604 chore: App router migration - Fix /event-types/[type] page, move getServerSideProps to /lib for event-types pages (#16457)
* event-types: refactor and extract client code into /modules

* revert

* remove res in getServerSideProps

* remove res in getServerSideProps 2

* Create EventTypeAppDir and fix error in event-types/[type]

* add comments

* fix type-check

* fix 1 more type-check

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2024-09-11 02:41:46 +00:00
Benny JooandAnik Dhabal Babu 976013512c perf: Server-Side Data Fetching in App Router: /workflows (#16563)
* wip

* complete server side fetching for app router

* fix type error

* fix

* address comments

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-10 19:25:59 -07:00
Benny Joo d9777a3011 perf: Server-Side Data Fetching in App Router: /availability (#16536)
* wip

* add method to OrganizationRepository

* server side fetching for availability

* fix error

* server side fetching finish

* remove log

* fix

* fix

* fix type

* no need to export

* fix type

* address nit comments
2024-09-10 19:23:42 -07:00
Benny JooandUdit Takkar 7725adedc8 chore: App router migration (org/[orgSlug]/instant-meeting), add missing page (#16448)
* Create event repository

* Use repository in event.handler

* fix type check

* migrate org/instant-meeting

* add export default

* fix metadata

* move getServerSideProps from @server/lib to @lib

* fix

* fix

* revert unneeded changes

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2024-09-10 18:43:50 -07:00
Anik Dhabal Babu 7269b3ea60 revert: booking rejection reason from booking success page (#16584) 2024-09-11 03:51:36 +05:30
Anik Dhabal Babu c168df4df0 fix: booking response field's label is not translated (#16582) 2024-09-10 23:39:32 +02:00
Keith Williams be9b0fb9a8 perf: Insights - put teamId filter first (#16581) 2024-09-10 19:40:19 +00:00
VijayandAnik Dhabal Babu c056cabbbd fix: to allow paypal install on team when user already installed (#16553)
* fix to allow paypal install on team when user already installed

* handle if parseInt fails

* Update add.ts

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-11 00:06:10 +09:00
97630e8add fix: prevent creating multiple platform orgs (#16564)
* fix: prevent creating multiple platform orgs

* fixup! fix: prevent creating multiple platform orgs

* fixup! fixup! fix: prevent creating multiple platform orgs

* Bust cache in CI

* Update schema.prisma

---------

Co-authored-by: Hariom <hariombalhara@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-11 00:05:22 +09:00
VijayandAnik Dhabal Babu a5443ccfbe fix to show updated values in eventTypes list (#16569)
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-11 00:05:02 +09:00
Alex van Andel 6f2986e42e chore: Release v4.4.7 (#16574)
release.yml / release (push) Canceled after 0s
2024-09-10 16:00:47 +01:00
Alex van Andel db345de99e fix: Add missing URL encoding to scheduledBy (#16573) 2024-09-10 13:49:23 +00:00
Keith WilliamsandAnik Dhabal Babu bde40dceb3 chore: Remove separate OR queries for Insights (#16568)
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-10 13:31:36 +00:00
Hariom BalharaandAnik Dhabal Babu 1a86e7c506 Skip COEP tests (#16572)
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2024-09-10 13:12:59 +00:00
Benny JooandKeith Williams 9ed1624111 chore: App router migration - settings/platform/**/*, settings/organizations/new and settings/organizations/[id]/* (#16334)
* remove WizardLayoutAppDir

* refactor organizations/new and add platform/new

* refactor organizations/[id]/*

* add APP_ROUTER_SETTINGS_ORG_ENABLED

* fix type error

* fix organizations/new page

* remove code not needed and fix type errors

* Fix Metadata utils

* remove unnecessary code

* remove unneeded code

* wip

* do not remove buildWrappedOnboardTeamMembersPage

* fix type error

* do not introduce changes to yarn.lock

* fix wrong route name

* fix onboard members

* fix platform pages

* fix settings/platform main view

* add requiresLicense to WithLayout

* refactor

* add requiresLicense to platform/new

* Add LicenseRequired back to platform/new

* add env variable

* fix onboard-members

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2024-09-09 17:19:44 -07:00
Benny Joo 5dff1c6df0 chore: App router migration - /attributes, /privacy, /dsync, /license-key under /settings route group (#16406)
* migrate license-key/new

* migrate settings/org/dsync

* migrate settings/org/privacy

* migrate org attributes

* remove res in getServerSideProps

* Fix SettingsLayoutAppDir

* fix attributes pages

* fix

* fix
2024-09-09 17:19:12 -07:00
Benny JooandJoe Au-Yeung 706d7dff42 perf: Server-Side Data Fetching in App Router: SettingsLayout / AdminLayout (#16537)
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
2024-09-09 14:38:51 -07:00
Keith Williams 71443ef23d perf: use isTeamBooking filter in all of Insights (#16561) 2024-09-09 18:50:20 +00:00
Keith Williams 17201334b6 Modified the view to use UNION for user/team bookings (#16558) 2024-09-10 03:05:38 +09:00
Peer Richelsen bc82ff4d21 Update and rename bug_report.yml to bug_report.md (#16556)
* Update and rename bug_report.yml to bug_report.md

* Update bug_report.md

* Update bug_report.md
2024-09-09 17:13:02 +00:00
Benny Joo 71ae3f157a chore: Fix bundle error occurring in Next.js Bundle Analysis CI job (#16548)
* fix bundle error

* revert
2024-09-09 22:25:25 +09:00
Rajiv SahalandKeith Williams 8784be067f chore: fix input DTOs for v2 calendar busy times endpoint (#16526)
* add class-transformer package to type

* update input dtos for get busy times and fix type issue

* fixup

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2024-09-09 09:26:16 +00:00
84a2e55125 chore: App router migration - general settings (#16312)
* added lockedSMS to future routes

* add orgMigrations routes to future

* correct metadata

* small fix

* add orgMigrations to future

* Move components to client components

* Remove tRPC element from edit user RSC

* Get username for meta

* Remove suspense query

* Remove orgMigrations from app router

* Type fix

* Revert "Remove suspense query"

This reverts commit eadd814f6e4a5d6856d9218342b7909c22fe62c6.

* Handle suspenseQuery in app router

* User edit page, fetch data server side

* Update yarn.lock

* Export getFixedT

* Set PageWrapper as root layout for settings

* Settings Layout accepts strings for shell heading

* Add OOO to app router settings

* Refactor layout for my-account pages

* Remove instances of pages router from my-account

* Refactor security pages

* Add billing to app router

* Add admin API link to layout

* Add api keys page

* Webhooks WIP

* Refactor SettingsHeader to client component

* Add webhook pages

* Refactor API keys page

* Add admin app page

* Type fix

* fix types

* fix developer/webhooks/[id] param value type error

* remove unnecessary code

* do not pass t prop to CreateNewWebhookButton

* fix type errors in webhook-edit-view

* fix the remaining type errors

* do not use prisma directly in generateMetadata

* remove use client if unnecessary

* Remove unused shell heading from SettingsLayoutAppDir

* improve metadata

* fix billing page

* fix import in settings/teams

* Use next `notFound()`

* fix type check

* fix type check

* remove unused code

* Fix calendar setting page

* Separate settings pages into route groups

* Refactor admin settings pages

* Remove meta instance from billing page route

* Update settings layoutAppDir

* Refactor developer settings pages

* Refactor out of office

* Refactor my account settings

* Refactor admin api page

* Refactor security pages

* Type fix

* fix styling in settings layout

---------

Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
2024-09-09 01:15:03 -04:00
Calcom BotandReplexica 21e23f32ac feat: update translations (#16532)
Co-authored-by: Replexica <support@replexica.com>
2024-09-07 19:30:52 -03:00
Anik Dhabal Babu 33aa9420af fix: fixed the flaky e2e tests that failed the most times and refactor (#16364)
* fix: fixed the flaky tests that failed maximum times

* Update action-based.e2e.ts

* another

* add

* add another

* update

* fix

* add

* fix

* update

* update and add

* fix

* update

* update

* chnages

* chore: updates

* reafactor and following best practice

* fix

* add and update

* update

* update and fix

* fix type

* another test

* update

* Update organization-invitation.e2e.ts

* refactor and update

* fix

* final update
2024-09-07 18:52:55 -03:00
Hariom Balhara ef0ba48f49 fix: Invalid options for Select and MultiSelect when both legacy and new options(i.e. with and without id are present) (#16509)
* Fix invalid select options

* Add test for multiselect filling and fix bug with csv reporting

* Fix options getting duplicated

* Add getQueryBuilderConfig tests
2024-09-07 03:07:47 +00:00
Emilio Degiovanni 6e54c459a4 fix: #16083. booking location editable (#16142) 2024-09-06 20:01:35 +00:00
f5c16f0d6b feat: OOO webhook and zapier (#15434)
* zapier and webhook

* instructions for zapier

* Fix types

* fix types

* revert adding zap template

* Update packages/app-store/zapier/README.md

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* Update packages/app-store/zapier/README.md

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* Update packages/app-store/zapier/README.md

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* Update packages/features/webhooks/lib/scheduleTrigger.ts

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* wip

* Fixes from comments, no more sendPayloadNoBooking

* fix subscriberOptions teamIds param type

* types

* Update packages/features/webhooks/lib/sendPayload.ts

* Re add zapierPayload to don't break old zaps

* instead of metadata use oooEntry inside webhookPayload

* undo comment message

* Types

* reset changes on yarn.lock

* review changes

* fix types

* fix types

* tentative fix for types in webhook

* type improvements

* fix description + clean up

* revert yarn.lock changes

* allow custom template for ooo entry

* type fixes

* type fix

* fix donwloadLinks in payload

* simplify some types

* allow array or number for teamId

* same payload for test trigger

* code clean up

* fix no show e2e test

* translate text for webhook payload and fix conditional

* add test for ooo_created webhooks

* reset files

* merge fix

* fix test data test id

* remove unused variable

* only trigger for accepted memberships

* remove unused variable

---------

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2024-09-06 15:48:05 -04:00
Morgan 105e7d3e28 chore: booker atom username / teams props enabled queries (#16514) 2024-09-06 12:38:37 -07:00
Morgan 21ef1900e9 chore: get platform me from trpc instead of apiv2 (#16515) 2024-09-06 12:36:47 -07:00
Peer Richelsen f07b73dc79 chore: updated cookie usage i18n (#16530) 2024-09-06 18:36:02 +00:00
Benny Joo d4b0516235 chore: App router migration - (/more, /maintenance, /connect-and-join, /upgrade) finish migration (#16497)
* more: extract client component into /modules folder

* maintenance: extract client component into /modules folder

* upgrade: extract client component into /modules folder

* improve WithLayout wrapper

* connect-and-join: extract client component into /modules folder

* add env vars
2024-09-06 17:22:05 +00:00
Calcom BotandReplexica 7bfad11ff9 feat: update translations (#16524)
Co-authored-by: Replexica <support@replexica.com>
2024-09-07 02:01:17 +09:00
d2f7a427d0 chore: App-router-migration(/apps) fix metadata, extract components into /module and finish migration (#16354)
* fix metadata for apps page

* migrate apps route to modules

* migrate apps/[slug]

* migrate apps/[slug]/setup

* migrate apps/categories/**/*

* add apps/installed page to app router

* migrate apps/[slug]/[...pages]

* migrate apps/installed/**/*

* Add apps/installation/[[...step]] to App router

* fix imports

* add missing use client directive

* finish migration

* fix metadata

* fix metadata for apps/categories

* fix type for installation/[[...step]]

* fix type for apps/[slug]/[...pages]

* remove unnecessary code

* refactor

* fix apps/installation

* move getServerSideProps to lib

* fix import of apps/installation

* fix import for app slug page

* refactor

* fix installation page in app router

* remove res in getServerSideProps

* replace setHeader with NextResponse header setHeader

* refactor installed pages

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2024-09-06 15:40:19 +00:00
Morgan a910eb96ad chore: improve typing of runSeparateQueriesForOrStatements (#16525)
* chore: improve typing of runSeparateQueriesForOrStatements

* fixup! chore: improve typing of runSeparateQueriesForOrStatements

* fixup! fixup! chore: improve typing of runSeparateQueriesForOrStatements

* fixup! fixup! fixup! chore: improve typing of runSeparateQueriesForOrStatements
2024-09-06 14:50:33 +00:00
Keith Williams c080458faa fix: Broken preview deployments (#16523) 2024-09-06 12:58:41 +00:00
Keith Williams 5c75cfc17f chore: make generic function for separate or queries (#16522)
* trying to create generic function for ors

* chore: Add generic function to run separate queries for OR

* Refactored getTotalNoShows to use separate queries

* Finished noshows

* Made the no shows logic handle single result
2024-09-06 12:27:05 +00:00
Keith Williams 4280f556cb chore: Add last batch of languages to translate with AI (#16520) 2024-09-06 12:26:22 +00:00
Syed Ali Shahbaz 21368bb130 Update FeedbackTable.tsx (#16521) 2024-09-06 11:21:07 +00:00
Benny Joo e9076c8e3e Refactor AppProvidersAppDir (#16496) 2024-09-06 08:53:25 +00:00
2471ee801b feat: hashed link retrieval from event types v1 api (#16437)
* add hashed link retrieval from event types api v1

* remove id, eventTypeId from hashedLink field

* Update event-type.ts

* Update event-type.ts

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2024-09-06 06:47:23 +00:00
+6 9fc9876b3f refactor: allow managed event tests parallel runs (#16113)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Replexica <support@replexica.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Udit Takkar <udit222001@gmail.com>
Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: unknown <adhabal2002@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2024-09-06 05:32:16 +00:00
Omar López 34ca3bd22d fix: flakyness on booking questions tests (#16513) 2024-09-06 07:20:25 +05:30
Anik Dhabal Babu bebe1dd7b4 chore: improved lastused login method (#16511) 2024-09-05 23:19:24 +05:30
fced9a6355 feat: Add step in team creation form for selecting event type and create a team event (#15286)
* feat: Create team event on a new team creation

* fix

* fixed failed tests

* move team event type form

* fix type error

* requested chnages

* update

* some update and refactor

* fix e2e test

* Update useCreateEventType.ts

* update

* fix type error

* fix e2e

* update

---------

Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2024-09-05 12:33:18 -04:00
625 changed files with 20737 additions and 8813 deletions
+6
View File
@@ -334,6 +334,8 @@ AB_TEST_BUCKET_PROBABILITY=50
# whether we redirect to the future/event-types from event-types or not
APP_ROUTER_EVENT_TYPES_ENABLED=0
APP_ROUTER_SETTINGS_ADMIN_ENABLED=0
APP_ROUTER_SETTINGS_PLATFORM_ENABLED=0
APP_ROUTER_SETTINGS_ORG_ENABLED=0
APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0
APP_ROUTER_APPS_SLUG_ENABLED=0
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
@@ -357,6 +359,10 @@ APP_ROUTER_AUTH_SAML_ENABLED=0
APP_ROUTER_AUTH_ERROR_ENABLED=0
APP_ROUTER_AUTH_PLATFORM_ENABLED=0
APP_ROUTER_AUTH_OAUTH2_ENABLED=0
APP_ROUTER_MORE_ENABLED=0
APP_ROUTER_MAINTENANCE_ENABLED=0
APP_ROUTER_UPGRADE_ENABLED=0
APP_ROUTER_CONNECT_AND_JOIN_ENABLED=0
# disable setry server source maps
SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN=1
+39
View File
@@ -0,0 +1,39 @@
---
name: Bug report
about: Report any issues with the platform
title: ""
labels: ["🐛 bug"]
assignees: ""
---
Found a bug? Please fill out the sections below. 👍
### Issue Summary
A summary of the issue. This needs to be a clear detailed-rich summary.
### Steps to Reproduce
1. (for example) Went to ...
2. Clicked on...
3. ...
Any other relevant information. For example, why do you consider this a bug and what did you expect to happen instead?
### Actual Results
- What's happening right now that is different from what is expected
### Expected Results
- This is an ideal result that the system should get after the tests are performed
### Technical details
- Browser version, screen recording, console logs, network requests: You can make a recording with [Bird Eats Bug](https://birdeatsbug.com/).
- Node.js version
- Anything else that you think could be an issue.
### Evidence
- How was this tested? This is quite mandatory in terms of bugs. Providing evidence of your testing with screenshots or/and videos is an amazing way to prove the bug and a troubleshooting chance to find the solution.
-49
View File
@@ -1,49 +0,0 @@
---
name: Bug report
about: Please make sure you have checked for any duplicate issues
title: ""
labels: ["🐛 bug"]
assignees: ""
---
### Is your proposal related to a problem?
<!--
Provide a clear and concise description of what the problem is.
For example, "I'm always frustrated when..."
-->
(Write your answer here.)
### Describe the solution you'd like
<!--
Provide a clear and concise description of what you want to happen.
-->
(Describe your proposed solution here.)
### Describe alternatives you've considered
<!--
Let us know about other solutions you've tried or researched.
-->
(Write your answer here.)
### Additional context
<!--
Is there anything else you can add about the proposal?
You might want to link to related issues here, if you haven't already.
-->
(Write your answer here.)
### Requirement/Document
<!--
Is there any type of document that could support that feature?
-->
(Share it here.)
-28
View File
@@ -1,28 +0,0 @@
name: PR Reviewed
on:
pull_request_review:
types: [submitted]
jobs:
label-pr:
runs-on: ubuntu-latest
permissions:
actions: read
issues: write
pull-requests: write
steps:
- name: Label PR as ready for E2E
if: github.event.review.state == 'approved'
uses: actions/github-script@v4
with:
script: |
await github.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: process.env.labels.split(', '),
})
env:
github_token: ${{ secrets.READY_FOR_E2E_PAT }}
labels: 'ready-for-e2e'
@@ -168,6 +168,7 @@ export const schemaEventTypeReadPublic = EventType.pick({
metadata: jsonSchema.nullable(),
customInputs: customInputSchema.array().optional(),
link: z.string().optional(),
hashedLink: z.object({ link: z.string() }).optional().nullable(),
bookingFields: eventTypeBookingFields.optional().nullable(),
})
);
@@ -51,6 +51,7 @@ export async function getHandler(req: NextApiRequest) {
where: { id },
include: {
customInputs: true,
hashedLink: { select: { link: true } },
team: { select: { slug: true } },
hosts: { select: { userId: true, isFixed: true } },
owner: { select: { username: true, id: true } },
@@ -56,6 +56,7 @@ async function getHandler(req: NextApiRequest) {
},
include: {
customInputs: true,
hashedLink: { select: { link: true } },
team: { select: { slug: true } },
hosts: { select: { userId: true, isFixed: true } },
owner: { select: { username: true, id: true } },
+1
View File
@@ -215,6 +215,7 @@ const generateTeamCheckoutSession = async ({
metadata: {
pendingPaymentTeamId,
ownerId,
dubCustomerId: ownerId, // pass the userId during checkout creation for sales conversion tracking: https://d.to/conversions/stripe
},
});
+1 -1
View File
@@ -28,7 +28,7 @@
"dependencies": {
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.33",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.34",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -5,7 +5,8 @@ import { BadRequestException, UnauthorizedException } from "@nestjs/common";
import { Injectable } from "@nestjs/common";
import { SUCCESS_STATUS, APPLE_CALENDAR_TYPE, APPLE_CALENDAR_ID } from "@calcom/platform-constants";
import { symmetricEncrypt, CalendarService } from "@calcom/platform-libraries";
import { symmetricEncrypt, CalendarService, symmetricDecrypt } from "@calcom/platform-libraries";
import { Credential } from "@calcom/prisma/client";
@Injectable()
export class AppleCalendarService implements CredentialSyncCalendarApp {
@@ -61,26 +62,70 @@ export class AppleCalendarService implements CredentialSyncCalendarApp {
if (username.length <= 1 || password.length <= 1)
throw new BadRequestException(`Username or password cannot be empty`);
const data = {
type: APPLE_CALENDAR_TYPE,
key: symmetricEncrypt(
JSON.stringify({ username, password }),
process.env.CALENDSO_ENCRYPTION_KEY || ""
),
userId: userId,
teamId: null,
appId: APPLE_CALENDAR_ID,
invalid: false,
};
const existingAppleCalendarCredentials = await this.credentialRepository.getAllUserCredentialsByTypeAndId(
APPLE_CALENDAR_TYPE,
userId
);
let hasMatchingUsernameAndPassword = false;
if (existingAppleCalendarCredentials.length > 0) {
const hasCalendarWithGivenCredentials = existingAppleCalendarCredentials.find(
(calendarCredential: Credential) => {
const decryptedKey = JSON.parse(
symmetricDecrypt(calendarCredential.key as string, process.env.CALENDSO_ENCRYPTION_KEY || "")
);
if (decryptedKey.username === username) {
if (decryptedKey.password === password) {
hasMatchingUsernameAndPassword = true;
}
return true;
}
}
);
if (!!hasCalendarWithGivenCredentials && hasMatchingUsernameAndPassword) {
return {
status: SUCCESS_STATUS,
};
}
if (!!hasCalendarWithGivenCredentials && !hasMatchingUsernameAndPassword) {
await this.credentialRepository.upsertAppCredential(
APPLE_CALENDAR_TYPE,
symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY || ""),
userId,
hasCalendarWithGivenCredentials.id
);
return {
status: SUCCESS_STATUS,
};
}
}
try {
const data = {
type: APPLE_CALENDAR_TYPE,
key: symmetricEncrypt(
JSON.stringify({ username, password }),
process.env.CALENDSO_ENCRYPTION_KEY || ""
),
userId: userId,
teamId: null,
appId: APPLE_CALENDAR_ID,
invalid: false,
};
const dav = new CalendarService({
id: 0,
...data,
user: { email: userEmail },
});
await dav?.listCalendars();
await this.credentialRepository.createAppCredential(APPLE_CALENDAR_TYPE, data.key, userId);
await this.credentialRepository.upsertAppCredential(APPLE_CALENDAR_TYPE, data.key, userId);
} catch (reason) {
throw new BadRequestException(`Could not add this apple calendar account: ${reason}`);
}
@@ -6,6 +6,7 @@ import {
} from "@/modules/credentials/credentials.repository";
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
import { UsersRepository } from "@/modules/users/users.repository";
import {
Injectable,
@@ -15,9 +16,11 @@ import {
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { User } from "@prisma/client";
import { Prisma } from "@prisma/client";
import { DateTime } from "luxon";
import { z } from "zod";
import { APPS_TYPE_ID_MAPPING } from "@calcom/platform-constants";
import { getConnectedDestinationCalendars, getBusyCalendarTimes } from "@calcom/platform-libraries";
import { Calendar } from "@calcom/platform-types";
import { PrismaClient } from "@calcom/prisma";
@@ -33,7 +36,8 @@ export class CalendarsService {
private readonly calendarsRepository: CalendarsRepository,
private readonly dbRead: PrismaReadService,
private readonly dbWrite: PrismaWriteService,
private readonly config: ConfigService
private readonly config: ConfigService,
private readonly selectedCalendarsRepository: SelectedCalendarsRepository
) {}
async getCalendars(userId: number) {
@@ -145,4 +149,32 @@ export class CalendarsService {
throw new NotFoundException("Calendar credentials not found");
}
}
async createAndLinkCalendarEntry(
userId: number,
externalId: string,
key: Prisma.InputJsonValue,
calendarType: keyof typeof APPS_TYPE_ID_MAPPING,
credentialId?: number | null
) {
const credential = await this.credentialsRepository.upsertAppCredential(
calendarType,
key,
userId,
credentialId
);
await this.selectedCalendarsRepository.upsertSelectedCalendar(
externalId,
credential.id,
userId,
calendarType
);
}
async checkCalendarCredentialValidity(userId: number, credentialId: number, type: string) {
const credential = await this.credentialsRepository.getUserCredentialById(userId, credentialId, type);
return !credential?.invalid;
}
}
@@ -131,11 +131,6 @@ export class GoogleCalendarService implements OAuthCalendarApp {
const token = await oAuth2Client.getToken(parsedCode);
// Google oAuth Credentials are stored in token.tokens
const key = token.tokens;
const credential = await this.credentialRepository.createAppCredential(
GOOGLE_CALENDAR_TYPE,
key as Prisma.InputJsonValue,
ownerId
);
oAuth2Client.setCredentials(key);
@@ -149,10 +144,39 @@ export class GoogleCalendarService implements OAuthCalendarApp {
const primaryCal = cals.data.items?.find((cal) => cal.primary);
if (primaryCal?.id) {
await this.selectedCalendarsRepository.createSelectedCalendar(
primaryCal.id,
credential.id,
const alreadyExistingSelectedCalendar = await this.selectedCalendarsRepository.getUserSelectedCalendar(
ownerId,
GOOGLE_CALENDAR_TYPE,
primaryCal.id
);
if (alreadyExistingSelectedCalendar) {
const isCredentialValid = await this.calendarsService.checkCalendarCredentialValidity(
ownerId,
alreadyExistingSelectedCalendar.credentialId ?? 0,
GOOGLE_CALENDAR_TYPE
);
// user credential probably got expired in this case
if (!isCredentialValid) {
await this.calendarsService.createAndLinkCalendarEntry(
ownerId,
alreadyExistingSelectedCalendar.externalId,
key as Prisma.InputJsonValue,
GOOGLE_CALENDAR_TYPE,
alreadyExistingSelectedCalendar.credentialId
);
}
return {
url: redir || origin,
};
}
await this.calendarsService.createAndLinkCalendarEntry(
ownerId,
primaryCal.id,
key as Prisma.InputJsonValue,
GOOGLE_CALENDAR_TYPE
);
}
@@ -168,16 +168,39 @@ export class OutlookService implements OAuthCalendarApp {
const defaultCalendar = await this.getDefaultCalendar(office365OAuthCredentials.access_token);
if (defaultCalendar?.id) {
const credential = await this.credentialRepository.createAppCredential(
const alreadyExistingSelectedCalendar = await this.selectedCalendarsRepository.getUserSelectedCalendar(
ownerId,
OFFICE_365_CALENDAR_TYPE,
office365OAuthCredentials,
ownerId
defaultCalendar.id
);
await this.selectedCalendarsRepository.createSelectedCalendar(
defaultCalendar.id,
credential.id,
if (alreadyExistingSelectedCalendar) {
const isCredentialValid = await this.calendarsService.checkCalendarCredentialValidity(
ownerId,
alreadyExistingSelectedCalendar.credentialId ?? 0,
OFFICE_365_CALENDAR_TYPE
);
// user credential probably got expired in this case
if (!isCredentialValid) {
await this.calendarsService.createAndLinkCalendarEntry(
ownerId,
alreadyExistingSelectedCalendar.externalId,
office365OAuthCredentials,
OFFICE_365_CALENDAR_TYPE,
alreadyExistingSelectedCalendar.credentialId
);
}
return {
url: redir || origin,
};
}
await this.calendarsService.createAndLinkCalendarEntry(
ownerId,
defaultCalendar.id,
office365OAuthCredentials,
OFFICE_365_CALENDAR_TYPE
);
}
@@ -0,0 +1,71 @@
import { ApiProperty as DocsProperty } from "@nestjs/swagger";
import { Transform } from "class-transformer";
import { IsString, IsBoolean, IsOptional, IsEnum, Matches } from "class-validator";
export enum TemplateType {
CHECK_IN_APPOINTMENT = "CHECK_IN_APPOINTMENT",
CUSTOM_TEMPLATE = "CUSTOM_TEMPLATE",
}
export class CreatePhoneCallInput {
@IsString()
@Matches(/^\+[1-9]\d{1,14}$/, {
message:
"Invalid phone number format. Expected format: +<CountryCode><PhoneNumber> with no spaces or separators.",
})
@DocsProperty({ description: "Your phone number" })
yourPhoneNumber!: string;
@IsString()
@Matches(/^\+[1-9]\d{1,14}$/, {
message:
"Invalid phone number format. Expected format: +<CountryCode><PhoneNumber> with no spaces or separators.",
})
@DocsProperty({ description: "Number to call" })
numberToCall!: string;
@IsString()
@DocsProperty({ description: "CAL API Key" })
calApiKey!: string;
@IsBoolean()
@DocsProperty({ description: "Enabled status", default: true })
enabled = true;
@IsEnum(TemplateType)
@DocsProperty({ description: "Template type", enum: TemplateType })
templateType: TemplateType = TemplateType.CUSTOM_TEMPLATE;
@IsOptional()
@IsString()
@DocsProperty({ description: "Scheduler name" })
schedulerName?: string;
@IsOptional()
@IsString()
@Transform(({ value }) => (value ? value : undefined))
@DocsProperty({ description: "Guest name" })
guestName?: string;
@IsOptional()
@IsString()
@Transform(({ value }) => (value ? value : undefined))
@DocsProperty({ description: "Guest email" })
guestEmail?: string;
@IsOptional()
@IsString()
@Transform(({ value }) => (value ? value : undefined))
@DocsProperty({ description: "Guest company" })
guestCompany?: string;
@IsOptional()
@IsString()
@DocsProperty({ description: "Begin message" })
beginMessage?: string;
@IsOptional()
@IsString()
@DocsProperty({ description: "General prompt" })
generalPrompt?: string;
}
@@ -0,0 +1,28 @@
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsEnum, IsString, ValidateNested } from "class-validator";
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
class Data {
@IsString()
@ApiProperty()
callId!: string;
@IsString()
@ApiProperty()
agentId!: string;
}
export class CreatePhoneCallOutput {
@ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
@ApiProperty({
type: Data,
})
@ValidateNested()
@Type(() => Data)
data!: Data;
}
@@ -1,10 +1,20 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsEnum } from "class-validator";
import { IsEnum, IsNumber, IsString } from "class-validator";
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
export class ProviderVerifyClientData {
@IsString()
clientId!: string;
@IsNumber()
organizationId!: number;
@IsString()
name!: string;
}
export class ProviderVerifyClientOutput {
@ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
data!: ProviderVerifyClientData;
}
@@ -40,6 +40,11 @@ export class CalProviderController {
return {
status: SUCCESS_STATUS,
data: {
clientId: oAuthClient.id,
organizationId: oAuthClient.organizationId,
name: oAuthClient.name,
},
};
}
@@ -9,12 +9,12 @@ import { APPS_TYPE_ID_MAPPING } from "@calcom/platform-constants";
export class CredentialsRepository {
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
async createAppCredential(
async upsertAppCredential(
type: keyof typeof APPS_TYPE_ID_MAPPING,
key: Prisma.InputJsonValue,
userId: number
userId: number,
credentialId?: number | null
) {
const credential = await this.getByTypeAndUserId(type, userId);
return this.dbWrite.prisma.credential.upsert({
create: {
type,
@@ -27,7 +27,7 @@ export class CredentialsRepository {
invalid: false,
},
where: {
id: credential?.id ?? 0,
id: credentialId ?? 0,
},
});
}
@@ -36,6 +36,10 @@ export class CredentialsRepository {
return this.dbWrite.prisma.credential.findFirst({ where: { type, userId } });
}
getAllUserCredentialsByTypeAndId(type: string, userId: number) {
return this.dbRead.prisma.credential.findMany({ where: { type, userId } });
}
getUserCredentialsByIds(userId: number, credentialIds: number[]) {
return this.dbRead.prisma.credential.findMany({
where: {
@@ -60,6 +64,30 @@ export class CredentialsRepository {
},
});
}
async getUserCredentialById(userId: number, credentialId: number, type: string) {
return await this.dbRead.prisma.credential.findUnique({
where: {
userId,
type,
id: credentialId,
},
select: {
id: true,
type: true,
key: true,
userId: true,
teamId: true,
appId: true,
invalid: true,
user: {
select: {
email: true,
},
},
},
});
}
}
export type CredentialsWithUserEmail = Awaited<
@@ -6,6 +6,7 @@ import { DestinationCalendarsController } from "@/modules/destination-calendars/
import { DestinationCalendarsRepository } from "@/modules/destination-calendars/destination-calendars.repository";
import { DestinationCalendarsService } from "@/modules/destination-calendars/services/destination-calendars.service";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
import { UsersRepository } from "@/modules/users/users.repository";
import { Module } from "@nestjs/common";
@@ -19,6 +20,7 @@ import { Module } from "@nestjs/common";
UsersRepository,
CredentialsRepository,
AppsRepository,
SelectedCalendarsRepository,
],
controllers: [DestinationCalendarsController],
exports: [DestinationCalendarsRepository],
@@ -1,3 +1,5 @@
import { CreatePhoneCallInput } from "@/ee/event-types/event-types_2024_06_14/inputs/create-phone-call.input";
import { CreatePhoneCallOutput } from "@/ee/event-types/event-types_2024_06_14/outputs/create-phone-call.output";
import { API_VERSIONS_VALUES } from "@/lib/api-versions";
import { PlatformPlan } from "@/modules/auth/decorators/billing/platform-plan.decorator";
import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator";
@@ -33,6 +35,7 @@ import {
import { ApiTags as DocsTags } from "@nestjs/swagger";
import { SUCCESS_STATUS } from "@calcom/platform-constants";
import { handleCreatePhoneCall } from "@calcom/platform-libraries";
import {
CreateTeamEventTypeInput_2024_06_14,
GetTeamEventTypesQuery_2024_06_14,
@@ -91,6 +94,30 @@ export class OrganizationsEventTypesController {
};
}
@Roles("TEAM_ADMIN")
@Post("/teams/:teamId/event-types/:eventTypeId/create-phone-call")
@UseGuards(ApiAuthGuard, IsOrgGuard, IsTeamInOrg, RolesGuard)
async createPhoneCall(
@Param("eventTypeId") eventTypeId: number,
@Param("orgId", ParseIntPipe) orgId: number,
@Body() body: CreatePhoneCallInput,
@GetUser() user: UserWithProfile
): Promise<CreatePhoneCallOutput> {
const data = await handleCreatePhoneCall({
user: {
id: user.id,
timeZone: user.timeZone,
profile: { organization: { id: orgId } },
},
input: { ...body, eventTypeId },
});
return {
status: SUCCESS_STATUS,
data,
};
}
@UseGuards(IsOrgGuard, IsTeamInOrg, IsAdminAPIEnabledGuard)
@Get("/teams/:teamId/event-types")
async getTeamEventTypes(
@@ -138,7 +165,7 @@ export class OrganizationsEventTypesController {
@Patch("/teams/:teamId/event-types/:eventTypeId")
async updateTeamEventType(
@Param("teamId", ParseIntPipe) teamId: number,
@Param("eventTypeId") eventTypeId: number,
@Param("eventTypeId", ParseIntPipe) eventTypeId: number,
@GetUser() user: UserWithProfile,
@Body() bodyEventType: UpdateTeamEventTypeInput_2024_06_14
): Promise<UpdateTeamEventTypeOutput> {
@@ -6,7 +6,7 @@ import { Injectable } from "@nestjs/common";
export class SelectedCalendarsRepository {
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
createSelectedCalendar(externalId: string, credentialId: number, userId: number, integration: string) {
upsertSelectedCalendar(externalId: string, credentialId: number, userId: number, integration: string) {
return this.dbWrite.prisma.selectedCalendar.upsert({
create: {
userId,
@@ -38,6 +38,18 @@ export class SelectedCalendarsRepository {
});
}
getUserSelectedCalendar(userId: number, integration: string, externalId: string) {
return this.dbRead.prisma.selectedCalendar.findUnique({
where: {
userId_integration_externalId: {
userId,
externalId,
integration,
},
},
});
}
async addUserSelectedCalendar(
userId: number,
integration: string,
@@ -68,7 +68,6 @@ export class UsersRepository {
}
async findByIdWithProfile(userId: number): Promise<UserWithProfile | null> {
console.log("findByIdWithProfile");
return this.dbRead.prisma.user.findUnique({
where: {
id: userId,
+185 -7
View File
@@ -1982,6 +1982,54 @@
]
}
},
"/v2/organizations/{orgId}/teams/{teamId}/event-types/{eventTypeId}/create-phone-call": {
"post": {
"operationId": "OrganizationsEventTypesController_createPhoneCall",
"parameters": [
{
"name": "eventTypeId",
"required": true,
"in": "path",
"schema": {
"type": "number"
}
},
{
"name": "orgId",
"required": true,
"in": "path",
"schema": {
"type": "number"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreatePhoneCallInput"
}
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreatePhoneCallOutput"
}
}
}
}
},
"tags": [
"Organizations Event Types"
]
}
},
"/v2/organizations/{orgId}/teams/event-types": {
"get": {
"operationId": "OrganizationsEventTypesController_getTeamsEventTypes",
@@ -3324,7 +3372,31 @@
"/v2/calendars/busy-times": {
"get": {
"operationId": "CalendarsController_getBusyTimes",
"parameters": [],
"parameters": [
{
"name": "loggedInUsersTz",
"required": true,
"in": "query",
"description": "The timezone of the logged in user represented as a string",
"example": "America/New_York",
"schema": {
"type": "string"
}
},
{
"name": "calendarsToLoad",
"required": true,
"in": "query",
"description": "An array of Calendar objects representing the calendars to be loaded",
"example": "[{ credentialId: \"1\", externalId: \"AQgtJE7RnHEeyisVq2ENs2gAAAgEGAAAACgtJE7RnHEeyisVq2ENs2gAAAhSDAAAA\" }, { credentialId: \"2\", externalId: \"AQM7RnHEeyisVq2ENs2gAAAhFDBBBBB\" }]",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
],
"responses": {
"200": {
"description": "",
@@ -7794,6 +7866,90 @@
"data"
]
},
"CreatePhoneCallInput": {
"type": "object",
"properties": {
"yourPhoneNumber": {
"type": "string",
"pattern": "/^\\+[1-9]\\d{1,14}$/",
"description": "Your phone number"
},
"numberToCall": {
"type": "string",
"pattern": "/^\\+[1-9]\\d{1,14}$/",
"description": "Number to call"
},
"calApiKey": {
"type": "string",
"description": "CAL API Key"
},
"enabled": {
"type": "object",
"default": true,
"description": "Enabled status"
},
"templateType": {
"default": "CUSTOM_TEMPLATE",
"enum": [
"CHECK_IN_APPOINTMENT",
"CUSTOM_TEMPLATE"
],
"type": "string",
"description": "Template type"
},
"schedulerName": {
"type": "string",
"description": "Scheduler name"
},
"guestName": {
"type": "string",
"description": "Guest name"
},
"guestEmail": {
"type": "string",
"description": "Guest email"
},
"guestCompany": {
"type": "string",
"description": "Guest company"
},
"beginMessage": {
"type": "string",
"description": "Begin message"
},
"generalPrompt": {
"type": "string",
"description": "General prompt"
}
},
"required": [
"yourPhoneNumber",
"numberToCall",
"calApiKey",
"enabled",
"templateType"
]
},
"CreatePhoneCallOutput": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/Data"
}
},
"required": [
"status",
"data"
]
},
"GetTeamEventTypesOutput": {
"type": "object",
"properties": {
@@ -8636,7 +8792,8 @@
"MEETING_STARTED",
"RECORDING_READY",
"INSTANT_MEETING",
"RECORDING_TRANSCRIPTION_GENERATED"
"RECORDING_TRANSCRIPTION_GENERATED",
"OOO_CREATED"
]
},
"active": {
@@ -8709,7 +8866,8 @@
"MEETING_STARTED",
"RECORDING_READY",
"INSTANT_MEETING",
"RECORDING_TRANSCRIPTION_GENERATED"
"RECORDING_TRANSCRIPTION_GENERATED",
"OOO_CREATED"
]
},
"active": {
@@ -9313,6 +9471,25 @@
"status"
]
},
"ProviderVerifyClientData": {
"type": "object",
"properties": {
"clientId": {
"type": "string"
},
"organizationId": {
"type": "number"
},
"name": {
"type": "string"
}
},
"required": [
"clientId",
"organizationId",
"name"
]
},
"ProviderVerifyClientOutput": {
"type": "object",
"properties": {
@@ -9323,10 +9500,14 @@
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/ProviderVerifyClientData"
}
},
"required": [
"status"
"status",
"data"
]
},
"ProviderVerifyAccessTokenOutput": {
@@ -10281,9 +10462,6 @@
"rescheduleUid": {
"type": "string"
},
"recurringEventId": {
"type": "string"
},
"timeZone": {
"type": "string"
},
+6
View File
@@ -8,6 +8,8 @@ import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME }
const ROUTES: [URLPattern, boolean][] = [
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
["/settings/admin/:path*", process.env.APP_ROUTER_SETTINGS_ADMIN_ENABLED === "1"] as const,
["/settings/platform/:path*", process.env.APP_ROUTER_SETTINGS_PLATFORM_ENABLED === "1"] as const,
["/settings/organizations/:path*", process.env.APP_ROUTER_SETTINGS_ORG_ENABLED === "1"] as const,
["/apps/installed/:category", process.env.APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED === "1"] as const,
["/apps/:slug", process.env.APP_ROUTER_APPS_SLUG_ENABLED === "1"] as const,
["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const,
@@ -28,6 +30,10 @@ const ROUTES: [URLPattern, boolean][] = [
["/bookings/:status", process.env.APP_ROUTER_BOOKINGS_STATUS_ENABLED === "1"] as const,
["/video/:path*", process.env.APP_ROUTER_VIDEO_ENABLED === "1"] as const,
["/teams", process.env.APP_ROUTER_TEAMS_ENABLED === "1"] as const,
["/more", process.env.APP_ROUTER_MORE_ENABLED === "1"] as const,
["/maintenance", process.env.APP_ROUTER_MAINTENANCE_ENABLED === "1"] as const,
["/upgrade", process.env.APP_ROUTER_UPGRADE_ENABLED === "1"] as const,
["/connect-and-join", process.env.APP_ROUTER_CONNECT_AND_JOIN_ENABLED === "1"] as const,
["/availability", process.env.APP_ROUTER_AVAILABILITY_ENABLED === "1"] as const,
].map(([pathname, enabled]) => [
new URLPattern({
+1 -1
View File
@@ -22,7 +22,7 @@ const create = async (locale: string, ns: string) => {
return _i18n;
};
const getFixedT = async (locale: string, ns: string) => {
export const getFixedT = async (locale: string, ns = "common") => {
const i18n = await create(locale, ns);
return i18n.getFixedT(locale, ns);
@@ -1,46 +1,17 @@
import LegacyPage, { getLayout } from "@pages/apps/[slug]/[...pages]";
import type { PageProps, SearchParams } from "app/_types";
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { SearchParams } from "app/_types";
import { _generateMetadata } from "app/_utils";
import type { GetServerSidePropsContext } from "next";
import { WithLayout } from "app/layoutHOC";
import type { GetServerSidePropsResult } from "next";
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { cookies, headers } from "next/headers";
import { notFound, redirect } from "next/navigation";
import { notFound } from "next/navigation";
import z from "zod";
import { getAppWithMetadata } from "@calcom/app-store/_appRegistry";
import RoutingFormsRoutingConfig, {
serverSidePropsConfig,
} from "@calcom/app-store/routing-forms/pages/app-routing.config";
import TypeformRoutingConfig from "@calcom/app-store/typeform/pages/app-routing.config";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import prisma from "@calcom/prisma";
import type { AppGetServerSideProps } from "@calcom/types/AppGetServerSideProps";
import type { AppProps } from "@lib/app-providers";
import { getServerSideProps } from "@lib/apps/[slug]/[...pages]/getServerSideProps";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import PageWrapper from "@components/PageWrapperAppDir";
import { ssrInit } from "@server/lib/ssr";
type AppPageType = {
getServerSideProps: AppGetServerSideProps;
// A component than can accept any properties
// eslint-disable-next-line @typescript-eslint/no-explicit-any
default: ((props: any) => JSX.Element) &
Pick<AppProps["Component"], "isBookingPage" | "getLayout" | "PageWrapper">;
};
type Found = {
notFound: false;
Component: AppPageType["default"];
getServerSideProps: AppPageType["getServerSideProps"];
};
const AppsRouting = {
"routing-forms": RoutingFormsRoutingConfig,
typeform: TypeformRoutingConfig,
};
import LegacyPage, { getLayout } from "~/apps/[slug]/[...pages]/pages-view";
const paramsSchema = z.object({
slug: z.string(),
@@ -60,127 +31,22 @@ export const generateMetadata = async ({
return notFound();
}
const mainPage = p.data.pages[0];
if (mainPage === "forms") {
return await _generateMetadata(
() => `Forms`,
() => ""
);
}
const legacyContext = buildLegacyCtx(headers(), cookies(), params, searchParams);
const { form } = await getPageProps(legacyContext);
const data = await getData(legacyContext);
const form = "form" in data ? (data.form as { name?: string; description?: string }) : null;
const formName = form?.name ?? "Forms";
const formDescription = form?.description ?? "";
return await _generateMetadata(
() => `${form.name}`,
() => form.description
() => formName,
() => formDescription
);
};
function getRoute(appName: string, pages: string[]) {
const routingConfig = AppsRouting[appName as keyof typeof AppsRouting] as Record<string, AppPageType>;
const getData = withAppDirSsr<GetServerSidePropsResult<any>>(getServerSideProps);
if (!routingConfig) {
notFound();
}
const mainPage = pages[0];
const appPage = routingConfig.layoutHandler || (routingConfig[mainPage] as AppPageType);
const getServerSidePropsHandler = serverSidePropsConfig[mainPage];
if (!appPage) {
notFound();
}
return {
notFound: false,
Component: appPage.default,
...appPage,
getServerSideProps: getServerSidePropsHandler,
} as Found;
}
const getPageProps = async ({ params, query, req }: GetServerSidePropsContext) => {
const p = paramsSchema.safeParse(params);
if (!p.success) {
return notFound();
}
const { slug: appName, pages } = p.data;
const route = getRoute(appName, pages);
if (route.notFound) {
return route;
}
if (route.getServerSideProps) {
// TODO: Document somewhere that right now it is just a convention that filename should have appPages in it's name.
// appPages is actually hardcoded here and no matter the fileName the same variable would be used.
// We can write some validation logic later on that ensures that [...appPages].tsx file exists
params!.appPages = pages.slice(1);
const ctx = { req, params, query };
const session = await getServerSession({ req });
const user = session?.user;
const app = await getAppWithMetadata({ slug: appName });
if (!app) {
notFound();
}
const result = await route.getServerSideProps(
{
...ctx,
params: {
...ctx.params,
appPages: pages.slice(1),
},
} as GetServerSidePropsContext<{
slug: string;
pages: string[];
appPages: string[];
}>,
prisma,
user,
ssrInit
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
if (result.notFound) {
notFound();
}
if (result.redirect) {
redirect(result.redirect.destination);
}
return {
appName,
appUrl: app.simplePath || `/apps/${appName}`,
...result.props,
};
} else {
return {
appName,
};
}
};
export default async function Page({ params, searchParams }: PageProps) {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;
const legacyContext = buildLegacyCtx(h, cookies(), params, searchParams);
const props = await getPageProps(legacyContext);
return (
<PageWrapper getLayout={getLayout} requiresLicense={false} nonce={nonce} themeBasis={null} {...props}>
<LegacyPage {...props} />
</PageWrapper>
);
}
export default WithLayout({
getLayout,
getData,
Page: LegacyPage,
});
+8 -8
View File
@@ -1,21 +1,21 @@
import Page from "@pages/apps/[slug]/index";
import { Prisma } from "@prisma/client";
import { withAppDirSsg } from "app/WithAppDirSsg";
import type { PageProps } from "app/_types";
import type { PageProps as _PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import type { InferGetStaticPropsType } from "next";
import { cookies, headers } from "next/headers";
import prisma from "@calcom/prisma";
import { AppRepository } from "@calcom/lib/server/repository/app";
import { getStaticProps } from "@lib/apps/[slug]/getStaticProps";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
type Y = InferGetStaticPropsType<typeof getStaticProps>;
const getData = withAppDirSsg<Y>(getStaticProps);
import type { PageProps } from "~/apps/[slug]/slug-view";
import Page from "~/apps/[slug]/slug-view";
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const getData = withAppDirSsg<PageProps>(getStaticProps);
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
const legacyContext = buildLegacyCtx(headers(), cookies(), params, searchParams);
const res = await getData(legacyContext);
@@ -27,7 +27,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
export const generateStaticParams = async () => {
try {
const appStore = await prisma.app.findMany({ select: { slug: true } });
const appStore = await AppRepository.findAppStore();
return appStore.map(({ slug }) => ({ slug }));
} catch (e: unknown) {
if (e instanceof Prisma.PrismaClientInitializationError) {
@@ -1,20 +1,19 @@
import Page from "@pages/apps/[slug]/setup";
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps as _PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import type { InferGetServerSidePropsType } from "next";
import { getServerSideProps } from "@calcom/app-store/_pages/setup/_getServerSideProps";
export const generateMetadata = async ({ params }: { params: Record<string, string | string[]> }) => {
import Page, { type PageProps } from "~/apps/[slug]/setup/setup-view";
export const generateMetadata = async ({ params }: _PageProps) => {
return await _generateMetadata(
() => `${params.slug}`,
() => ""
);
};
type T = InferGetServerSidePropsType<typeof getServerSideProps>;
const getData = withAppDirSsr<T>(getServerSideProps);
const getData = withAppDirSsr<PageProps>(getServerSideProps);
export default WithLayout({ getLayout: null, Page, getData });
@@ -1,18 +1,18 @@
import CategoryPage, { type PageProps } from "@pages/apps/categories/[category]";
import { withAppDirSsg } from "app/WithAppDirSsg";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { APP_NAME } from "@calcom/lib/constants";
import { AppCategories } from "@calcom/prisma/enums";
import { isPrismaAvailableCheck } from "@calcom/prisma/is-prisma-available-check";
import { getStaticProps } from "@lib/apps/categories/[category]/getStaticProps";
import CategoryPage, { type PageProps } from "~/apps/categories/[category]/category-view";
export const generateMetadata = async () => {
return await _generateMetadata(
() => `${APP_NAME}`,
() => ""
() => "Apps Store",
() => "Connecting people, technology and the workplace."
);
};
+4 -3
View File
@@ -1,14 +1,15 @@
import Page from "@pages/apps/categories/index";
import { withAppDirSsr } from "app/WithAppDirSsr";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { getServerSideProps } from "@lib/apps/categories/getServerSideProps";
import Page from "~/apps/categories/categories-view";
export const generateMetadata = async () => {
return await _generateMetadata(
() => `Categories`,
() => ""
() => "Apps Store",
() => "Connecting people, technology and the workplace."
);
};
@@ -0,0 +1,25 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { getServerSideProps } from "@lib/apps/installation/[[...step]]/getServerSideProps";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import type { OnboardingPageProps } from "~/apps/installation/[[...step]]/step-view";
import Page from "~/apps/installation/[[...step]]/step-view";
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
const { appMetadata } = await getData(legacyCtx);
return await _generateMetadata(
(t) => `${t("install")} ${appMetadata?.name ?? ""}`,
() => ""
);
};
const getData = withAppDirSsr<OnboardingPageProps>(getServerSideProps);
export default WithLayout({ getLayout: null, getData, Page });
@@ -1,17 +1,18 @@
import Page from "@pages/apps/installed/[category]";
import { withAppDirSsr } from "app/WithAppDirSsr";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { getServerSideProps } from "@lib/apps/installed/[category]/getServerSideProps";
import { getServerSidePropsAppDir } from "@lib/apps/installed/[category]/getServerSideProps";
import Page from "~/apps/installed/[category]/installed-category-view";
export const generateMetadata = async () => {
return await _generateMetadata(
(t) => `${t("installed_apps")}`,
(t) => t("installed_apps"),
(t) => t("manage_your_connected_apps")
);
};
const getData = withAppDirSsr(getServerSideProps);
const getData = withAppDirSsr(getServerSidePropsAppDir);
export default WithLayout({ getLayout: null, getData, Page });
@@ -0,0 +1,7 @@
import { redirect } from "next/navigation";
const Page = () => {
redirect("/apps/installed/calendar");
};
export default Page;
+9 -7
View File
@@ -1,18 +1,20 @@
import AppsPage from "@pages/apps";
import { withAppDirSsr } from "app/WithAppDirSsr";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/MainLayoutAppDir";
import { APP_NAME } from "@calcom/lib/constants";
import { getServerSideProps } from "@lib/apps/getServerSideProps";
import AppsPage, { LayoutWrapper } from "~/apps/apps-view";
export const generateMetadata = async () => {
return await _generateMetadata(
() => `Apps | ${APP_NAME}`,
() => ""
(t) => t("app_store"),
(t) => t("app_store_description")
);
};
export default WithLayout({ getLayout, getData: withAppDirSsr(getServerSideProps), Page: AppsPage });
export default WithLayout({
getLayout: LayoutWrapper,
getData: withAppDirSsr(getServerSideProps),
Page: AppsPage,
});
+3 -9
View File
@@ -1,11 +1,10 @@
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import PageWrapper from "@components/PageWrapperAppDir";
import { ssrInit } from "@server/lib/ssr";
import Logout from "~/auth/logout-view";
@@ -20,7 +19,6 @@ export const generateMetadata = async () => {
const Page = async ({ params, searchParams }: PageProps) => {
// cookie will be cleared in `/apps/web/middleware.ts`
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;
const context = buildLegacyCtx(h, cookies(), params, searchParams);
const ssr = await ssrInit(context);
const props = {
@@ -28,11 +26,7 @@ const Page = async ({ params, searchParams }: PageProps) => {
query: context.query,
};
return (
<PageWrapper requiresLicense={false} getLayout={null} nonce={nonce} themeBasis={null}>
<Logout {...props} />
</PageWrapper>
);
return <Logout {...props} />;
};
export default Page;
export default WithLayout({ getLayout: null, ServerPage: Page })<"P">;
@@ -1,8 +1,12 @@
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { notFound } from "next/navigation";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import { ScheduleRepository } from "@calcom/lib/server/repository/schedule";
import { TravelScheduleRepository } from "@calcom/lib/server/repository/travelSchedule";
import { UserRepository } from "@calcom/lib/server/repository/user";
import { AvailabilitySettingsWebWrapper } from "~/availability/[schedule]/schedule-view";
@@ -23,4 +27,46 @@ export const generateMetadata = async ({ params }: PageProps) => {
);
};
export default WithLayout({ getLayout: null, Page: AvailabilitySettingsWebWrapper });
const Page = async ({ params }: PageProps) => {
if (params?.schedule) {
notFound();
}
const scheduleId = Number(params.schedule);
const session = await getServerSessionForAppDir();
const userId = session?.user?.id;
if (!userId) {
notFound();
}
let userData, schedule, travelSchedules;
try {
userData = await UserRepository.getTimeZoneAndDefaultScheduleId({
userId,
});
if (!userData?.timeZone || !userData?.defaultScheduleId) {
throw new Error("timeZone and defaultScheduleId not found");
}
} catch (e) {
notFound();
}
try {
schedule = await ScheduleRepository.findDetailedScheduleById({
scheduleId,
isManagedEventType: false,
userId,
timeZone: userData.timeZone,
defaultScheduleId: userData.defaultScheduleId,
});
} catch (e) {}
try {
travelSchedules = await TravelScheduleRepository.findTravelSchedulesByUserId(userId);
} catch (e) {}
return <AvailabilitySettingsWebWrapper scheduleFetched={schedule} travelSchedules={travelSchedules} />;
};
export default WithLayout({ ServerPage: Page });
+24 -1
View File
@@ -1,5 +1,9 @@
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { notFound } from "next/navigation";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
import AvailabilityPage from "~/availability/availability-view";
@@ -10,4 +14,23 @@ export const generateMetadata = async () => {
);
};
export default WithLayout({ getLayout: null, Page: AvailabilityPage });
const Page = async () => {
const session = await getServerSessionForAppDir();
const userId = session?.user?.id;
const orgId = session?.user?.org?.id;
if (!userId || !orgId) {
notFound();
}
try {
const currentOrg = await OrganizationRepository.findCurrentOrg({
orgId,
userId,
});
return <AvailabilityPage currentOrg={currentOrg} />;
} catch {
notFound();
}
};
export default WithLayout({ ServerPage: Page });
+10 -1
View File
@@ -1,4 +1,13 @@
import LegacyPage from "@pages/connect-and-join";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import LegacyPage from "~/connect-and-join/connect-and-join-view";
export const generateMetadata = async () => {
return await _generateMetadata(
() => "Connect and Join",
() => ""
);
};
export default WithLayout({ getLayout: null, Page: LegacyPage })<"P">;
@@ -1,21 +1,16 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { Params, SearchParams } from "app/_types";
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { cookies, headers } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import { getServerSideProps } from "@lib/event-types/[type]/getServerSideProps";
import type { PageProps as EventTypePageProps } from "@lib/event-types/[type]/getServerSideProps";
import EventTypePageWrapper from "~/event-types/views/event-types-single-view";
import { getServerSideProps } from "~/event-types/views/event-types-single-view.getServerSideProps";
export const generateMetadata = async ({
params,
searchParams,
}: {
params: Params;
searchParams: SearchParams;
}) => {
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
const { eventType } = await getData(legacyCtx);
@@ -26,5 +21,5 @@ export const generateMetadata = async ({
};
const getData = withAppDirSsr(getServerSideProps);
export default WithLayout({ getLayout: null, getData, Page: EventTypePageWrapper })<"P">;
const Page = (props: EventTypePageProps) => <EventTypePageWrapper {...props} isAppDir={true} />;
export default WithLayout({ getLayout: null, getData, Page })<"P">;
+3 -2
View File
@@ -1,12 +1,13 @@
import LegacyPage from "@pages/maintenance";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { APP_NAME } from "@calcom/lib/constants";
import LegacyPage from "~/maintenance/maintenance-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => `${t("under_maintenance")}`,
(t) => t("under_maintenance"),
(t) => t("under_maintenance_description", { appName: APP_NAME })
);
+10 -1
View File
@@ -1,4 +1,13 @@
import Page from "@pages/more";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import Page from "~/more/more-page-view";
export const generateMetadata = async () => {
return await _generateMetadata(
() => "More",
() => ""
);
};
export default WithLayout({ getLayout: null, Page })<"P">;
@@ -0,0 +1,42 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps as _PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { headers, cookies } from "next/headers";
import { getLayout } from "@calcom/features/MainLayoutAppDir";
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { EventRepository } from "@calcom/lib/server/repository/event";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import { getServerSideProps } from "@lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps";
import type { PageProps } from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/instant-meeting-view";
import Page from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/instant-meeting-view";
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
const { slug: eventSlug, user: username } = await getData(context);
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req, context.params?.orgSlug);
const org = isValidOrgDomain ? currentOrgDomain : null;
const event = await EventRepository.getPublicEvent({
username,
eventSlug,
isTeamEvent: true,
org,
fromRedirectOfNonOrgLink: context.query.orgRedirection === "true",
});
const profileName = event?.profile.name ?? "";
const title = event?.title ?? "";
return await _generateMetadata(
() => `${title} | ${profileName}`,
() => `${title}`
);
};
const getData = withAppDirSsr<PageProps>(getServerSideProps);
export default WithLayout({ getLayout, getData, Page })<"P">;
@@ -1,17 +1,11 @@
import { getServerSideProps } from "@pages/reschedule/[uid]";
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { SearchParams } from "app/_types";
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import type { PageProps } from "app/_types";
import { cookies, headers } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
import withEmbedSsr from "@lib/withEmbedSsr";
type PageProps = Readonly<{
params: Params;
searchParams: SearchParams;
}>;
const Page = async ({ params, searchParams }: PageProps) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
await withAppDirSsr(withEmbedSsr(getServerSideProps))(legacyCtx);
@@ -1,8 +1,7 @@
import { getServerSideProps } from "@pages/reschedule/[uid]";
import { withAppDirSsr } from "app/WithAppDirSsr";
import type { SearchParams } from "app/_types";
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { headers, cookies } from "next/headers";
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
@@ -13,11 +12,6 @@ export const generateMetadata = async () =>
() => ""
);
type PageProps = Readonly<{
params: Params;
searchParams: SearchParams;
}>;
const getData = withAppDirSsr(getServerSideProps);
const Page = async ({ params, searchParams }: PageProps) => {
+1 -7
View File
@@ -1,6 +1,5 @@
import { type SearchParams } from "app/_types";
import type { PageProps } from "app/_types";
import { type GetServerSidePropsContext } from "next";
import type { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { cookies, headers } from "next/headers";
import { redirect } from "next/navigation";
import z from "zod";
@@ -21,11 +20,6 @@ const getPageProps = async (context: GetServerSidePropsContext) => {
return redirect(`/apps/routing-forms/${pages.length ? pages.join("/") : ""}`);
};
type PageProps = Readonly<{
params: Params;
searchParams: SearchParams;
}>;
const Page = async ({ params, searchParams }: PageProps) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
await getPageProps(legacyCtx);
@@ -0,0 +1,33 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import AdminAppsList from "@calcom/features/apps/AdminAppsList";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("apps"),
(t) => t("admin_apps_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("apps")} description={t("admin_apps_description")}>
<div className="flex">
<AdminAppsList
baseURL="/settings/admin/apps"
classNames={{
appCategoryNavigationRoot: "overflow-x-scroll",
}}
/>
</div>
</SettingsHeader>
);
};
export default Page;
@@ -1,5 +1,5 @@
import Page from "@pages/settings/admin/apps/index";
import { _generateMetadata } from "app/_utils";
import { redirect } from "next/navigation";
export const generateMetadata = async () =>
await _generateMetadata(
@@ -7,4 +7,8 @@ export const generateMetadata = async () =>
(t) => t("admin_apps_description")
);
const Page = () => {
redirect("/[category]");
};
export default Page;
@@ -0,0 +1,20 @@
import { _generateMetadata } from "app/_utils";
import { FlagListingView } from "@calcom/features/flags/pages/flag-listing-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Feature Flags",
() => "Here you can toggle your Cal.com instance features."
);
const Page = async () => {
return (
<SettingsHeader title="Feature Flags" description="Here you can toggle your Cal.com instance features.">
<FlagListingView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,26 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import ImpersonationView from "~/settings/admin/impersonation-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("admin"),
(t) => t("impersonation")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("admin")} description={t("impersonation")}>
<ImpersonationView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,21 @@
import { _generateMetadata } from "app/_utils";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import LockedSMSView from "~/settings/admin/locked-sms-view";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Locked SMS",
() => "Lock or unlock SMS sending for users"
);
const Page = () => {
return (
<SettingsHeader title="Locked SMS" description="Lock or unlock SMS sending for users">
<LockedSMSView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,21 @@
import { _generateMetadata } from "app/_utils";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import LegacyPage from "~/settings/admin/oauth-view";
export const generateMetadata = async () =>
await _generateMetadata(
() => "OAuth",
() => "Add new OAuth Clients"
);
const Page = () => {
return (
<SettingsHeader title="OAuth" description="Add new OAuth Clients">
<LegacyPage />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,52 @@
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { notFound } from "next/navigation";
import { z } from "zod";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import { OrgForm } from "@calcom/features/ee/organizations/pages/settings/admin/AdminOrgEditPage";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
const orgIdSchema = z.object({ id: z.coerce.number() });
export const generateMetadata = async ({ params }: { params: Params }) => {
const input = orgIdSchema.safeParse(params);
if (!input.success) {
return await _generateMetadata(
() => `Editing organization`,
() => "Here you can edit an organization."
);
}
const org = await OrganizationRepository.adminFindById({ id: input.data.id });
return await _generateMetadata(
() => `Editing organization: ${org.name}`,
() => "Here you can edit an organization."
);
};
const Page = async ({ params }: { params: Params }) => {
const input = orgIdSchema.safeParse(params);
if (!input.success) notFound();
try {
const org = await OrganizationRepository.adminFindById({ id: input.data.id });
return (
<SettingsHeader
title={`Editing organization: ${org.name}`}
description="Here you can edit an organization.">
<LicenseRequired>
<OrgForm org={org} />
</LicenseRequired>
</SettingsHeader>
);
} catch {
notFound();
}
};
export default Page;
@@ -0,0 +1,28 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import AdminOrgTable from "@calcom/features/ee/organizations/pages/settings/admin/AdminOrgPage";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("organizations"),
(t) => t("orgs_page_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("organizations")} description={t("orgs_page_description")}>
<LicenseRequired>
<AdminOrgTable />
</LicenseRequired>
</SettingsHeader>
);
};
export default Page;
@@ -10,4 +10,4 @@ export const generateMetadata = async () =>
() => "admin_description"
);
export default WithLayout({ getLayout, Page: LegacyPage })<"P">;
export default WithLayout({ getServerLayout: getLayout, Page: LegacyPage })<"P">;
@@ -0,0 +1,52 @@
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { notFound } from "next/navigation";
import { z } from "zod";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import { UsersEditView } from "@calcom/features/ee/users/pages/users-edit-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { UserRepository } from "@calcom/lib/server/repository/user";
const userIdSchema = z.object({ id: z.coerce.number() });
export const generateMetadata = async ({ params }: { params: Params }) => {
const input = userIdSchema.safeParse(params);
if (!input.success) {
return await _generateMetadata(
() => `Editing user`,
() => "Here you can edit a current user."
);
}
const user = await UserRepository.adminFindById(input.data.id);
return await _generateMetadata(
() => `Editing user: ${user.username}`,
() => "Here you can edit a current user."
);
};
const Page = async ({ params }: { params: Params }) => {
const input = userIdSchema.safeParse(params);
if (!input.success) {
notFound();
}
try {
const user = await UserRepository.adminFindById(input.data.id);
return (
<SettingsHeader title="Editing user" description="Here you can edit a current user">
<LicenseRequired>
<UsersEditView user={user} />
</LicenseRequired>
</SettingsHeader>
);
} catch {
notFound();
}
};
export default Page;
@@ -0,0 +1,20 @@
import { _generateMetadata } from "app/_utils";
import UsersAddView from "@calcom/features/ee/users/pages/users-add-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Add new user",
() => "Here you can add a new user."
);
const Page = () => {
return (
<SettingsHeader title="Add new user" description="Here you can add a new user">
<UsersAddView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,30 @@
import { _generateMetadata } from "app/_utils";
import UsersListingView from "@calcom/features/ee/users/pages/users-listing-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { Button } from "@calcom/ui";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Users",
() => "A list of all the users in your account including their name, title, email and role."
);
const Page = () => {
return (
<SettingsHeader
title="Users"
description="A list of all the users in your account including their name, title, email and role."
CTA={
<div className="mt-4 space-x-5 sm:ml-16 sm:mt-0 sm:flex-none">
{/* TODO: Add import users functionality */}
{/* <Button disabled>Import users</Button> */}
<Button href="/settings/admin/users/add">Add user</Button>
</div>
}>
<UsersListingView />
</SettingsHeader>
);
};
export default Page;
@@ -2,4 +2,4 @@ import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@components/auth/layouts/AdminLayoutAppDir";
export default WithLayout({ getLayout })<"L">;
export default WithLayout({ getServerLayout: getLayout })<"L">;
@@ -0,0 +1,31 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import BillingView from "~/settings/billing/billing-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("billing"),
(t) => t("manage_billing_description")
);
const Page = async () => {
// FIXME: Refactor me once next-auth endpoint is migrated to App Router
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("billing")}
description={t("manage_billing_description")}
borderInShellHeader={true}>
<BillingView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,33 @@
import { getFixedT, _generateMetadata } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { APP_NAME } from "@calcom/lib/constants";
import ApiKeysView from "~/settings/developer/api-keys-view";
import NewApiKeyButton from "~/settings/developer/components/CreateApiKeyButton";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("api_keys"),
(t) => t("create_first_api_key_description", { appName: APP_NAME })
);
const Page = async () => {
// FIXME: Refactor me once next-auth endpoint is migrated to App Router
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("api_keys")}
description={t("create_first_api_key_description", { appName: APP_NAME })}
CTA={<NewApiKeyButton />}
borderInShellHeader={true}>
<ApiKeysView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,35 @@
import type { PageProps } from "app/_types";
import { getFixedT, _generateMetadata } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { EditWebhookView } from "@calcom/features/webhooks/pages/webhook-edit-view";
import { APP_NAME } from "@calcom/lib/constants";
import { WebhookRepository } from "@calcom/lib/server/repository/webhook";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("webhooks"),
(t) => t("add_webhook_description", { appName: APP_NAME })
);
const Page = async ({ params }: PageProps) => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
const id = typeof params?.id === "string" ? params.id : undefined;
const webhook = await WebhookRepository.findByWebhookId(id);
console.log("This is the webhook", webhook);
return (
<SettingsHeader
title={t("edit_webhook")}
description={t("add_webhook_description", { appName: APP_NAME })}
borderInShellHeader={true}
backButton>
<EditWebhookView webhook={webhook} />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,30 @@
import { getFixedT, _generateMetadata } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { NewWebhookView } from "@calcom/features/webhooks/pages/webhook-new-view";
import { APP_NAME } from "@calcom/lib/constants";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("webhooks"),
(t) => t("add_webhook_description", { appName: APP_NAME })
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("add_webhook")}
description={t("add_webhook_description", { appName: APP_NAME })}
borderInShellHeader={true}
backButton>
<NewWebhookView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,16 @@
import { _generateMetadata } from "app/_utils";
import { WebhooksViewAppDir } from "@calcom/features/webhooks/pages/webhooks-view";
import { APP_NAME } from "@calcom/lib/constants";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("webhooks"),
(t) => t("add_webhook_description", { appName: APP_NAME })
);
const Page = () => {
return <WebhooksViewAppDir />;
};
export default Page;
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout })<"L">;
@@ -0,0 +1,26 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import AppearancePage from "~/settings/my-account/appearance-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("appearance"),
(t) => t("appearance_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("appearance")} description={t("appearance_description")}>
<AppearancePage />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,40 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { Button } from "@calcom/ui";
import { CalendarListContainer } from "@components/apps/CalendarListContainer";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("calendars"),
(t) => t("calendars_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
const AddCalendarButton = () => {
return (
<>
<Button color="secondary" StartIcon="plus" href="/apps/categories/calendar">
{t("add_calendar")}
</Button>
</>
);
};
return (
<SettingsHeader
title={t("calendars")}
description={t("calendars_description")}
CTA={<AddCalendarButton />}>
<CalendarListContainer />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,39 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { Button } from "@calcom/ui";
import ConferencingView from "~/settings/my-account/conferencing-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("conferencing"),
(t) => t("conferencing_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
const AddConferencingButton = () => {
return (
<Button color="secondary" StartIcon="plus" href="/apps/categories/conferencing">
{t("add")}
</Button>
);
};
return (
<SettingsHeader
title={t("conferencing")}
description={t("conferencing_description")}
CTA={<AddConferencingButton />}
borderInShellHeader={true}>
<ConferencingView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,26 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import GeneralQueryView from "~/settings/my-account/general-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("general"),
(t) => t("general_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("general")} description={t("general_description")} borderInShellHeader={true}>
<GeneralQueryView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,30 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import CreateNewOutOfOfficeEntryButton from "@calcom/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton";
import { OutOfOfficeEntriesList } from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("out_of_office"),
(t) => t("out_of_office_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("out_of_office")}
description={t("out_of_office_description")}
CTA={<CreateNewOutOfOfficeEntryButton />}>
<OutOfOfficeEntriesList />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,30 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import { APP_NAME } from "@calcom/lib/constants";
import ProfileView from "~/settings/my-account/profile-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("profile"),
(t) => t("profile_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("profile")}
description={t("profile_description", { appName: APP_NAME })}
borderInShellHeader={true}>
<ProfileView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,28 @@
import { getFixedT, _generateMetadata } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import { AdminAPIView } from "@calcom/features/ee/organizations/pages/settings/admin-api";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => `${t("admin")} ${t("api_reference")}`,
(t) => t("leverage_our_api")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={`${t("admin")} ${t("api_reference")}`}
description={t("leverage_our_api")}
borderInShellHeader={false}>
<AdminAPIView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,11 @@
import { _generateMetadata } from "app/_utils";
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-edit-view";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Attribute",
(t) => t("edit_attribute_description")
);
export default Page;
@@ -0,0 +1,11 @@
import { _generateMetadata } from "app/_utils";
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-create-view";
export const generateMetadata = async () =>
await _generateMetadata(
() => "Attribute",
() => "Create an attribute for your team members"
);
export default Page;
@@ -0,0 +1,11 @@
import { _generateMetadata } from "app/_utils";
import Page from "@calcom/ee/organizations/pages/settings/attributes/attributes-list-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("attributes"),
(t) => t("attribute_meta_description")
);
export default Page;
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -1,6 +1,7 @@
import Page from "@pages/settings/billing/index";
import { _generateMetadata } from "app/_utils";
import Page from "~/settings/billing/billing-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("billing"),
@@ -0,0 +1,24 @@
import { _generateMetadata, getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import DirectorySyncTeamView from "@calcom/features/ee/dsync/page/team-dsync-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("directory_sync"),
(t) => t("directory_sync_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("directory_sync")} description={t("directory_sync_description")}>
<DirectorySyncTeamView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,24 @@
import { _generateMetadata, getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import PrivacyView from "@calcom/features/ee/organizations/pages/settings/privacy";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("privacy"),
(t) => t("privacy_organization_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("privacy")} description={t("privacy_organization_description")}>
<PrivacyView />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,5 @@
import { WithLayout } from "app/layoutHOC";
import { getLayout } from "@calcom/features/settings/appDir/SettingsLayoutAppDir";
export default WithLayout({ getServerLayout: getLayout });
@@ -0,0 +1,30 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import ProfileImpersonationViewWrapper from "~/settings/security/impersonation-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("impersonation"),
(t) => t("impersonation_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("impersonation")}
description={t("impersonation_description")}
borderInShellHeader={true}>
<ProfileImpersonationViewWrapper />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,27 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import PasswordViewWrapper from "~/settings/security/password-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("password"),
(t) => t("password_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader title={t("password")} description={t("password_description")} borderInShellHeader={true}>
<PasswordViewWrapper />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,29 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SAMLSSO from "@calcom/features/ee/sso/page/user-sso-view";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("sso_configuration"),
(t) => t("sso_configuration_description")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("sso_configuration")}
description={t("sso_configuration_description")}
borderInShellHeader={true}>
<SAMLSSO />
</SettingsHeader>
);
};
export default Page;
@@ -0,0 +1,29 @@
import { _generateMetadata } from "app/_utils";
import { getFixedT } from "app/_utils";
import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir";
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
import TwoFactorAuthView from "~/settings/security/two-factor-auth-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("two_factor_auth"),
(t) => t("add_an_extra_layer_of_security")
);
const Page = async () => {
const session = await getServerSessionForAppDir();
const t = await getFixedT(session?.user.locale || "en");
return (
<SettingsHeader
title={t("2fa")}
description={t("set_up_two_factor_authentication")}
borderInShellHeader={true}>
<TwoFactorAuthView />
</SettingsHeader>
);
};
export default Page;
@@ -1,6 +1,7 @@
import Page from "@pages/settings/billing/index";
import { _generateMetadata } from "app/_utils";
import Page from "~/settings/billing/billing-view";
export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("billing"),

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