Compare commits

...
279 Commits
Author SHA1 Message Date
zomars 140bb3836a v1.9.5 2022-09-12 17:12:38 -05:00
hexcowboyandOmar López 6b2d675043 add rainbowkit form to v2 event-types (#4349)
Co-authored-by: Omar López <zomars@me.com>
2022-09-12 17:11:20 -05:00
7e917cdcbb V2 settings teams (Profil, Members, Appearance View) (#4350)
* add team profile

* first version for team members page

* finish up design of member list item

* fix dialog buttons

* add missing seats and upgrading information

* add v2 dialog for changing role

* finish basic version of member's schedule

* remove modalContainer

* design fixes team profile page

* show only team info to non admins

* allow all member to check availabilities

* make time available heading sticky

* add dropdown for mobile view

* create team appearance view

* finish appearance page

* use settings layout and add danger zone for member

* add fallback logo

* Add teams to sidebar and fix UI

* add team invitations

* Clean up

* code clean up

* add impersontation and disable autofocus on calendar

* improve team info

* refactor teaminvitelist code and fix leaving a team

* add team pages to settings shell

* add link to create new team

* small fixes

* clean up comments

* V2 Multi-select (Team Select) (#4324)

* --init

* design improved

* further fine tuning

* more fixes

* removed extra JSX tag

* added story

* NIT

* revert to use of CheckedTeamSelect

* Removes comments

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

* fix: toggle alligment (#4361)

* fix: add checked tranform for switch (#4357)

* fixed input size on mobile, fixed settings (#4360)

* fix image uploader button in safari

* code clean up

* fixing type errors

* Moved v2 team components to features

Adds deprecation notices

* Update SettingsLayout.tsx

* Migrated to features and build fixes

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@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: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-12 17:04:33 -05:00
50f63ef000 Adds skeleton loader to workflows (#4402)
* fix event types skeleton loader

* fix margin in event types

* fix skeleton loader in bookings

* add skeleton loader for workflow list

* add skeleton loader for editing page

* fix border radius of skeleton loader

* fix mobile view workflow list

* add mobile view for skeleton list

* make multi select full with in mobile view

* mobile view for edit skeleton loader

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-12 16:51:36 -05:00
Udit Takkar 1deca816bd Feat/team owner booking (#3999)
* WIP: testing queries

* feat: add badge

* fix: get only id

* refactor: get bookings query

* WIP: display attendees added

* fix: add type
2022-09-12 15:41:59 -05:00
7e52e3d295 V2 Settings Shell - Add Teams Section & UI fixes (#4347)
* Add teams to sidebar and fix UI

* Clean up

* V2 Multi-select (Team Select) (#4324)

* --init

* design improved

* further fine tuning

* more fixes

* removed extra JSX tag

* added story

* NIT

* revert to use of CheckedTeamSelect

* Removes comments

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

* fix: toggle alligment (#4361)

* fix: add checked tranform for switch (#4357)

* fixed input size on mobile, fixed settings (#4360)

* fixing type errors

* Mobile fixes

* Tests fixes

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@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: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-12 20:26:42 +00:00
+7 ded1fce6fa V2 settings - developer view (#4085)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Create my account folder

* Add profile section

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* WIP

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Finish profile fields

* Show toast on success

* General tab WIP

* Even Type move order handles

* Add switching of destination calendar

* List calendar and delete

* Render empty screenwhen no calendars

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Transfer to SSR

* Appearance screen made

* V2 image uploader

* WIP appearance page

* Remove unnecessary data from viewer.me

* Add profile translations

* Add translations to general page

* Add calendar switch

* Add calendar switch

* Add translations to appearance page

* Clean up conferencing page

* Clean up appearance page

* Draft shell on md screen

* fixed slots availability by fixing buffertime (#3756)

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

* Hidding import features from other services (#3970)

* Update PULL_REQUEST_TEMPLATE.md

* Fixes CLS when loading Avatars (#3973)

* Fixes CLS when loading Avatars

* Update packages/ui/v2/core/Avatar.tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

Co-authored-by: Leo Giovanetti <hello@leog.me>

* New Crowdin translations by Github Action (#3954)

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>

* Adding continue button to connectCalendar on getting-started view  (#3971)

* Adding continue button to connectCalendar view getting-started

* Fixing extra space

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>

* 2.0 Settings / My Account {View} (#3874)

* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Create my account folder

* Add profile section

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* WIP

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Finish profile fields

* Show toast on success

* General tab WIP

* Even Type move order handles

* Add switching of destination calendar

* List calendar and delete

* Render empty screenwhen no calendars

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Transfer to SSR

* Appearance screen made

* V2 image uploader

* WIP appearance page

* Remove unnecessary data from viewer.me

* Add profile translations

* Add translations to general page

* Add calendar switch

* Add calendar switch

* Add translations to appearance page

* Clean up conferencing page

* Settings sidebar fixes

* Updates middleware

* Update SettingsLayout.tsx

* Settings layout improvements

* Type fix

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* AppStore CLI: Making video app creation a breeze with major cleanup of locations code throughout (#3825)

* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Add Embed ModalBox for routing forms

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Add duplicate form support

* Fix duplication logic

* Change to feathericons everywhere and other fixes

* Dont allow routes for fallback route

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Fix all TS issues

* Fix tests

* Troubleshoot container + Active on count

* Support routing using query params

* Improve mobile

* NITS

* Fix padding on input

* Support multiselect in router endpoint

* Fix the issue where app goes in embed mode after viewing embed once

* Fix icons

* Add router url tests

* Add Responses download and form toggling tests

* Add required validation test

* Change Icons everywhere

* App typeform app

* Improvements in cli

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Add typeform how-to-use page

* Add typeform how-to-use page and screenshots

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Fix TS error

* Add missing image

* Update CliApp.tsx

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Major locations cleanup, 10s of bug fixes and app-store improvements

* Fix missing pieces

* More fixes

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* more fixes

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Revert console

* Revert api

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* Fix TS errors

* Add missing import

* Fix CLI

* Add a default placeholder

* Remove hardcoded daily:integrations

* Fix message for payment page

* Revert api and console to main

* Update README

* Fix TS errors

* Fix Lint warnings

* Fix Tests

* Fix conflict issues

* Fix conflict issues

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>

* Button to test a workflow action (#3873)

* add Test action button + UI improvements

* add test action functionality

* add confirmation dialog before sending SMS

* code clean up

* show error message if test action fails

* disable test action button in edit mode

* fixes SMS testing

* use updated values

* fix wrongly updated data in useEffect

* fix typo

* code clean up

* fix UI issue in mobile view

* small design fix

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* Improve CLI App Help Text (#3982)

* Adds deprecation notice to QueryCell (#3977)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* added campfire.to app (#3984)

* fixed file size campfire (#3985)

* added campfire.to app

* fixed file size

* Draft shell on md screen

* Draft small settings bar

* Add padding to dropdown menu

* WIP

* Create mobile settings nav

* Fix conferencing render

* Only display mobile settings nav

* Clean up my account section

* Clean up

* Remove old draft shell

* Remove old draft shell

* Implement changes from #3817

* WIP

* Create webhooks page

* WIP Webhook form

* WIP

* WIP Webhook

* WIP

* Create edit webhook page

* Edit webhooks

* Edit API keys

* Update API key name

* Create embeds page

* Fix type errors

* Remove embeds page

* Improves Zapier response and payload (#3892)

* improve listBookings API call

* improve payload for zapier call

* use more readable location for integrations

* remove cancellation reason

* convert location to readbale string

* code clean up

* code clean up

* updated expected webhook response for e2e tests

* fix failing e2e

* revert webhook response

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* fixed dark mode team page (#4315)

* Checkly formatting

* Move hidden label to toggle on events page (#4320)

* Add events for routing forms

* Bring shell changes from main

* Clean up

* WIP

* V2 Multi-select (Team Select) (#4324)

* --init

* design improved

* further fine tuning

* more fixes

* removed extra JSX tag

* added story

* NIT

* revert to use of CheckedTeamSelect

* Removes comments

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

* fix: toggle alligment (#4361)

* fix: add checked tranform for switch (#4357)

* fixed input size on mobile, fixed settings (#4360)

* fixed input size on mobile, fixed settings (#4360)

* Fix merge errors

* Fix API key page

* Fix type error

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: Kszemi <mkrzemien11@gmail.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Noah <hi@noahflk.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2022-09-12 14:07:52 -05:00
sean-brydon 27f58c70d3 Fix px on suffix/prefix (#4395) 2022-09-12 13:43:09 +00:00
Udit Takkar 869ebb092b fix: add fit to height (#4372) 2022-09-12 13:30:05 +00:00
sean-brydon 5f3e9efa6d Oooops (#4386) 2022-09-12 10:55:41 +00:00
Carina Wollendorfer 078ca46a28 Fixes design issues in settings/appearance (#4375) 2022-09-12 10:27:35 +00:00
sean-brydon ef7863ad0b Simple animations (#4378) 2022-09-12 10:15:30 +00:00
Syed Ali Shahbazandkodiakhq[bot] 9557c1818b Fixes Dynamic Link description Logic (#4351)
* fixes logic

* fixes description

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-12 15:34:42 +05:30
20fd45a3fd V2 password reset design (#4327)
* using new v2 buttons in password reset

* Forgot password UI

* Logo updates

* change error copy

* Fix tests

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2022-09-12 09:25:54 +00:00
Carina Wollendorfer e6849174c1 Fixes security vulnerability in workflows (#4376) 2022-09-12 09:15:58 +02:00
sean-brydon a9b79eafb6 Add automanimate page transitions (#4368) 2022-09-11 21:54:05 +02:00
Peer Richelsen e50bc0f198 fixed input size on mobile, fixed settings (#4360) 2022-09-11 09:09:23 +00:00
Udit Takkar 63aae60af4 fix: add checked tranform for switch (#4357) 2022-09-10 17:52:35 +00:00
Udit Takkar c215f7de03 fix: toggle alligment (#4361) 2022-09-10 19:34:38 +02:00
Syed Ali ShahbazandPeer Richelsen 3ce687c0a4 V2 Multi-select (Team Select) (#4324)
* --init

* design improved

* further fine tuning

* more fixes

* removed extra JSX tag

* added story

* NIT

* revert to use of CheckedTeamSelect

* Removes comments

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-10 09:57:55 +00:00
20e9e9763a HOTFIX: Removes disabled state from reminder phone input (reschedule) (#4322)
* removes disabled state from reminder phone

* prefill phone number for sms reminder

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
2022-09-09 15:01:37 -04:00
Peer RichelsenandAlex van Andel 5cd2ce9246 a ton of mobile improvements to save space (#4336)
* made /booking more responsive friendly

* hiding headline and description on mobile, moving CTA to bottom right fixed on mobile

* more padding on full screen mode on iPhone

* nit fixes to wipemycal

* nit fixes to wipemycal

* lint fix

* Update apps/web/styles/globals.css

Massive nit, lol.

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-09 15:02:31 +00:00
770c35039d Feature/add availability tab (#4314)
* Add Availability Tab

* Some i18n fixups

* Update apps/web/components/v2/eventtype/AvailabilityTab.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Update apps/web/components/v2/eventtype/AvailabilityTab.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Update apps/web/components/v2/eventtype/AvailabilityTab.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Update apps/web/components/v2/eventtype/AvailabilityTab.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Fixed lint

* Oops

* Use classnames for SkeletonText instead of width,height

* Ditches QueryCell

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-09 15:47:17 +01:00
0cab371db4 Replace AdminLayout with SettingsLayout (#4311)
* Replace AdminLayout with SettingsLayout

* Revert "Replace AdminLayout with SettingsLayout"

This reverts commit cc30ddcb6aa7a61157d53e46d60054f1cc565796.

* Revert to changes

* Add back changes

* Few nits + translate language to each local language

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-09 12:57:31 +00:00
Alex van Andel 15a0216cc5 Removed deprecations (#4335) 2022-09-09 12:24:26 +00:00
Peer Richelsenandsean-brydon a385a4bb38 minor changes to routing forms (#4333)
* added new combined buttons on all pages

* fixed required label in routing forms

* i18n for routing forms, minor changes to mobile routing forms action items

* full width for routing forms descriptin on mobile

* i18n fixes

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2022-09-09 11:45:20 +00:00
Alex van Andel 5965129851 Checking if serial fixes the issue (not conflicting with any others) (#4331)
* Checking if serial fixes the issue (not conflicting with any others)

* Remove redundant check
2022-09-09 11:31:55 +00:00
sean-brydonandPeer Richelsen 3e92571078 Add rounded-none to combined buttons by default (#4330)
* Add rounded-none to combined buttons by default

* Remove combined

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-09 11:18:15 +00:00
Peer Richelsenandsean-brydon 83f0ba7ba4 added new combined buttons on all pages (#4328)
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2022-09-09 10:53:02 +00:00
b0de653166 fix/onboarding-no-more-flaky-tests (#4254)
* Change expects to don't wait for plain text

* Fix change password test flakiness

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-09 08:54:10 +00:00
Syed Ali Shahbazandkodiakhq[bot] 1c46370572 dynamic link description on availability page (#4323)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-09 08:40:58 +00:00
Omar Lópezandsean-brydon 99f11dcc5c Removes dynamic dimensions for V2 Skeletons in favor of classnames (#4263)
* WIP

* Removes dynamic width in favor of classnames

* Update useLocale.ts

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2022-09-09 08:22:39 +00:00
d7e523d365 Change flex to inline-flex (#4317)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-09 08:00:54 +00:00
Peer Richelsen 342c281f3c fix color for calcom logo on /video (#4326)
* fixed daily video logo

* nit
2022-09-09 09:44:25 +02:00
d0225824fb Hotfix Lark Get Times (#4321)
* Removed disconnected calendar notice

* fixes dark mode piblic page (#4201) (#4203)

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>

* fix cookie name (#4295)

* fix: lark get free busy param error (#4285)

Co-authored-by: chengcheng.frontend <chengcheng.frontend@bytedance.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* Revert "Removed disconnected calendar notice"

This reverts commit 638600a5b716aa989549ed8b103b35b185ecbdd6.

* Revert "fix cookie name (#4295)"

This reverts commit 1aefa0efb3986c44bc5faaf6e0765580cdaeb564.

Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: Cheng CHENG <c.cheng@live.cn>
Co-authored-by: chengcheng.frontend <chengcheng.frontend@bytedance.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-09 00:43:53 +00:00
Noah 79fd1bd76f Move hidden label to toggle on events page (#4320) 2022-09-08 16:26:51 -06:00
zomars 293c2ffb86 Checkly formatting 2022-09-08 16:04:40 -06:00
Peer Richelsen 4162d403e1 fixed dark mode team page (#4315) 2022-09-08 21:33:19 +00:00
bb24539731 Improves Zapier response and payload (#3892)
* improve listBookings API call

* improve payload for zapier call

* use more readable location for integrations

* remove cancellation reason

* convert location to readbale string

* code clean up

* code clean up

* updated expected webhook response for e2e tests

* fix failing e2e

* revert webhook response

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 13:18:00 -06:00
sean-brydonandPeer Richelsen 0b8eb3b8ec Modal updates (#4289)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-08 19:40:09 +02:00
38ccd7b159 fix: lark get free busy param error (#4285)
Co-authored-by: chengcheng.frontend <chengcheng.frontend@bytedance.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-08 19:39:23 +02:00
4aa9c830c1 feat: add a link tag (#4292)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:38:36 +02:00
0c2a25fb78 fix: toggle alignment, spacing, square btn (#4282)
* fix: toggle alignment, spacing, square btn

* fix: toggle alignment

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:38:11 +02:00
dce7973825 Fix UI issues (#4300)
* fix: increase font size to 14 px

* fix: double border issue

* fix: destructive button looks off from figma

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:37:26 +02:00
Peer Richelsenandkodiakhq[bot] 4771a1a64a first iteration of fixing dark mode, <Select> is missing (#4304)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:35:32 +02:00
Peer Richelsenandkodiakhq[bot] bb7087640d removed <hr> from event type apps (#4297)
* removed <hr> from event type apps, app settings need to be extracted into /packages/app-store/

* nit

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:34:49 +02:00
Peer Richelsenandkodiakhq[bot] d7ec335a34 added padding top for settings on desktop (#4280)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 19:34:13 +02:00
zomars 54f1eef308 Adds concurrency to workflows 2022-09-08 11:01:47 -06:00
Peer Richelsenandkodiakhq[bot] f1b95cd28d added n8n to app store (#4291)
* added n8n app to app store, gave padding to sticky app store header

* nit

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 18:34:01 +02:00
alannnc 6ee878aab0 fix cookie name (#4294) 2022-09-08 10:12:56 -06:00
1bb987556d Impersonate UI (#4243)
* Impersonate UI

* Depracates Old admin required

* Move permission container to features

* Remove logic from dumb components

* Fix export from v2

* Fix type cast - add tab filter

* Redirect on authed pages

* Add key back

Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2022-09-08 15:35:31 +00:00
github-actions[bot]andCrowdin Bot 306a1212cf New Crowdin translations by Github Action (#4279)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-08 16:58:08 +02:00
Peer Richelsen f7119849db addded padding to sticky nav, temp removed TODAY from /booking (#4278) 2022-09-08 14:34:37 +00:00
Alex van AndelandPeer Richelsen a8c1851c04 Fixes button styles on /event-types and /availability (#4281)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-08 14:21:46 +00:00
3c8cc4e624 fix: use flex (#4276)
* fix: use flex

* Update packages/ui/v2/core/Dialog.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peer@cal.com>
2022-09-08 13:22:09 +02:00
github-actions[bot]andCrowdin Bot 6958c710cf New Crowdin translations by Github Action (#4264)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-08 11:46:52 +02:00
38bd111260 fixes toggle (#4253)
* fixes toggle

* fix: remove absolute from recurring event div

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-08 11:42:46 +02:00
github-actions[bot]andCrowdin Bot 290fb8db55 New Crowdin translations by Github Action (#4235)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-08 10:53:11 +02:00
zomars 3e0f14ea29 Removed disconnected calendar notice 2022-09-07 19:10:24 -06:00
zomars 984281963e v1.9.4 2022-09-07 19:03:31 -06:00
zomars ec8be2994c Submodule sync 2022-09-07 19:03:14 -06:00
zomars 8996a2aa8e Adds opt-in banner to mobile "more" menu 2022-09-07 19:02:24 -06:00
4856ed9977 Signup Flow improvements (#4012)
* Get login working

* Update website

* Fixes

* Save

* svae

* Save

* Change translation key

* Various fixes after testing

* Update website

* Add TS Tests

* Upate website

* Fix tests

* Fix linting and other issues

* Fix linting and other issues

* Fix bugs found during recording of demos

* Revert default coookie change

* Self review fixe

* Link fixes

* Removed inline styles, cleanup

* Various fixes

* Added new envs to e2e

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-07 18:38:37 -06:00
Alex van Andel d36d925788 Feature/goal reduce flaky tests (#4247)
* Wait for current_password input to be visible

* Login flow remove duplication + small fix change-password

* Made hash-my-url more robust

* Wait until locale is ready to resolve test flackiness

* Added waitForSelector before trying to fill inputs
2022-09-07 17:29:24 -06:00
NoahandAlex van Andel de54d75cd3 Add delete tooltip to event detail (#4259)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-07 23:20:08 +00:00
NoahandAlex van Andel 70ac949bea Move hidden label to toggle on events page (#4261)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-07 22:40:50 +00:00
34408c5593 Add calendar source to busy blocks (#3074)
* Add calendar source to busy blocks

* Update troubleshoot.tsx

* Type fixes

* Adds sources to availablity

# Conflicts:
#	apps/web/pages/availability/troubleshoot.tsx

* Update troubleshoot v1 and v2 with source element

* Type fixes

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Alan <alannnc@gmail.com>
2022-09-07 13:28:43 -06:00
Joe Au-Yeung 7da272f67a Prevent saving error responses from Zoom to user credentials (#3743) 2022-09-07 18:18:11 +00:00
sean-brydonandPeer Richelsen 46e46bc1de Fixing spacing on event details (#4238)
* Fixing spacing on event details

* Shell pb 40px

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-07 16:28:58 +00:00
Peer Richelsen 7b36df9eb3 added raycast to app store (#4231) 2022-09-07 15:33:27 +00:00
Peer Richelsen b4d1cb0988 added desktop app layout for v2.0, changed 2.0 banner (#4242) 2022-09-07 09:01:33 -06:00
Carina WollendorferandCarinaWolli e52af8d387 fix design (#4226)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-09-07 14:05:25 +00:00
Peer Richelsen e9b6e5144a temp disabled onboarding test due to flakiness (#4236) 2022-09-07 13:25:11 +00:00
0c6c23e1b0 New Crowdin translations by Github Action (#4225)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-07 14:49:53 +02:00
Peer Richelsen 458406feaf fixed booking navbar, fixed bookings buttons, fixed /success dark mode (#4230) 2022-09-07 14:49:30 +02:00
Peer Richelsen b9fc3ac076 Update README.md 2022-09-07 13:08:06 +02:00
sean-brydon 00f5ba2ac5 Rounded divider + Fixing button group (#4233) 2022-09-07 11:04:12 +00:00
Syed Ali Shahbaz f1436da96c fixes overflow rounded border (#4227) 2022-09-07 09:26:22 +02:00
30f8d12563 added /more page for mobile (#4219)
* added /more page for mobile

* i18n

* Navigation improvements

* Reverting unused exports

* Improved performance for getting mobile/desktop items

* I take your forEach and up it with reduce

Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-06 22:13:31 -06:00
zomars 1561224dbb Type fixes 2022-09-06 21:25:17 -06:00
f3bedabf92 Fix/styles getting started v2 (#4224)
* Fixes spacings style

* Fix spacings

* Update test

* Fix router push when image upload is success, also typo

* Fix styles for mobile

* Sumodule sync

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-06 19:34:33 -06:00
58b3067b2b Hotfix Settings Shell (#4222)
* Add settings section prop to shell

* Clean up

* Adjustments

* Update Shell.tsx

* Update SettingsLayout.tsx

* Mobile drawer fixes

* Update VerticalTabItem.tsx

Co-authored-by: zomars <zomars@me.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-06 19:33:50 -06:00
zomars 6a6adf1c3c Submodule sync 2022-09-06 19:28:00 -06:00
zomars 2027447eab Takes you back to referer page on v2 opt-in 2022-09-06 19:18:47 -06:00
13c2dc24dc Feature/new onboarding page (#3377)
* [WIP] New design and components for onboarding page

* saving work in progress

* new fonts

* [WIP] new onboarding page, initial page, components

* WIP calendar connect

* WIP availability new design

* WIP onboarding page

* WIP onboarding, working new availability form

* WIP AvailabilitySchedule componente v2

* WIP availability with defaultSchedule

* User profile view

* Relocate new onboarding/getting-started page components

* Steps test for onboarding v2

* Remove logs and unused code

* remove any as types

* Adding translations

* Fixes translation text and css for step 4

* Deprecation note for old-getting-started

* Added defaul events and refetch user query when finishing getting-started

* Fix button text translation

* Undo schedule v1 changes

* Fix calendar switches state

* Add cookie to save return-to when connecting calendar

* Change useTranslation for useLocale instead

* Change test to work with data-testid instead of hardcoded plain text due to translation

* Fix skeleton containers for calendars

* Style fixes

* fix styles to match v2

* Fix styles and props types to match v2 design

* Bugfix/router and console errors (#4206)

* The loading={boolean} parameter is required, so this must be <Button />

* Fixes duplicate key error

* Use zod and router.query.step directly to power state machine

* use ul>li & divide for borders

* Update apps/web/components/getting-started/steps-views/ConnectCalendars.tsx

Co-authored-by: alannnc <alannnc@gmail.com>

* Linting

* Deprecation notices and type fixes

* Update CreateEventsOnCalendarSelect.tsx

* Type fixes

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-06 16:58:16 -06:00
7f2db86a83 updated workflows empty screen (#4218)
* updated workflows empty screen

* fix missing title

* small design fixes for cards

* add ... if workflow example exceeds 2 lines

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
2022-09-06 21:30:03 +00:00
91bc6ae820 V1->V2 connect calendar (#3961)
* V1->V2 connect calendar

* Fix imports

* Fix types

* Implementing v1 NoCalendarConnectedAlert changes on v2 component

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
2022-09-06 20:45:46 +00:00
Peer Richelsen 008706e5ac fixed i18n 2022-09-06 21:42:34 +02:00
zomars dad2fd098e Partial-Revert "V2/settings shell (#3987)"
This reverts commit 3a35eb413f.
2022-09-06 13:34:58 -06:00
Peer Richelsen c0b83c1df6 changed all new buttons, added i18n for routing forms (#4217) 2022-09-06 13:13:20 -06:00
Peer Richelsen 851fb25430 fixed height of recurring event select (#4213) 2022-09-06 13:01:05 -06:00
github-actions[bot]andCrowdin Bot 00d50f0285 New Crowdin translations by Github Action (#4214)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-06 20:55:34 +02:00
Peer Richelsen efc0bf6a5b event types new dropdown misaligned (#4216)
* fixed event type creation dropdown

* nit
2022-09-06 12:51:11 -06:00
Alex van AndelandPeer Richelsen dd9d7ab485 Added timeZone to v2, bugfix availabilityAsString (#4210)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-06 12:34:29 -06:00
+4 3a35eb413f V2/settings shell (#3987)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Create my account folder

* Add profile section

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* WIP

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Finish profile fields

* Show toast on success

* General tab WIP

* Even Type move order handles

* Add switching of destination calendar

* List calendar and delete

* Render empty screenwhen no calendars

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Transfer to SSR

* Appearance screen made

* V2 image uploader

* WIP appearance page

* Remove unnecessary data from viewer.me

* Add profile translations

* Add translations to general page

* Add calendar switch

* Add calendar switch

* Add translations to appearance page

* Clean up conferencing page

* Clean up appearance page

* Draft shell on md screen

* fixed slots availability by fixing buffertime (#3756)

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

* Hidding import features from other services (#3970)

* Update PULL_REQUEST_TEMPLATE.md

* Fixes CLS when loading Avatars (#3973)

* Fixes CLS when loading Avatars

* Update packages/ui/v2/core/Avatar.tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

Co-authored-by: Leo Giovanetti <hello@leog.me>

* New Crowdin translations by Github Action (#3954)

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>

* Adding continue button to connectCalendar on getting-started view  (#3971)

* Adding continue button to connectCalendar view getting-started

* Fixing extra space

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>

* 2.0 Settings / My Account {View} (#3874)

* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Create my account folder

* Add profile section

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* WIP

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Finish profile fields

* Show toast on success

* General tab WIP

* Even Type move order handles

* Add switching of destination calendar

* List calendar and delete

* Render empty screenwhen no calendars

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Transfer to SSR

* Appearance screen made

* V2 image uploader

* WIP appearance page

* Remove unnecessary data from viewer.me

* Add profile translations

* Add translations to general page

* Add calendar switch

* Add calendar switch

* Add translations to appearance page

* Clean up conferencing page

* Settings sidebar fixes

* Updates middleware

* Update SettingsLayout.tsx

* Settings layout improvements

* Type fix

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* AppStore CLI: Making video app creation a breeze with major cleanup of locations code throughout (#3825)

* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Add Embed ModalBox for routing forms

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Add duplicate form support

* Fix duplication logic

* Change to feathericons everywhere and other fixes

* Dont allow routes for fallback route

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Fix all TS issues

* Fix tests

* Troubleshoot container + Active on count

* Support routing using query params

* Improve mobile

* NITS

* Fix padding on input

* Support multiselect in router endpoint

* Fix the issue where app goes in embed mode after viewing embed once

* Fix icons

* Add router url tests

* Add Responses download and form toggling tests

* Add required validation test

* Change Icons everywhere

* App typeform app

* Improvements in cli

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Add typeform how-to-use page

* Add typeform how-to-use page and screenshots

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Fix TS error

* Add missing image

* Update CliApp.tsx

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Major locations cleanup, 10s of bug fixes and app-store improvements

* Fix missing pieces

* More fixes

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* more fixes

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Revert console

* Revert api

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* Fix TS errors

* Add missing import

* Fix CLI

* Add a default placeholder

* Remove hardcoded daily:integrations

* Fix message for payment page

* Revert api and console to main

* Update README

* Fix TS errors

* Fix Lint warnings

* Fix Tests

* Fix conflict issues

* Fix conflict issues

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>

* Button to test a workflow action (#3873)

* add Test action button + UI improvements

* add test action functionality

* add confirmation dialog before sending SMS

* code clean up

* show error message if test action fails

* disable test action button in edit mode

* fixes SMS testing

* use updated values

* fix wrongly updated data in useEffect

* fix typo

* code clean up

* fix UI issue in mobile view

* small design fix

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* Improve CLI App Help Text (#3982)

* Adds deprecation notice to QueryCell (#3977)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>

* added campfire.to app (#3984)

* fixed file size campfire (#3985)

* added campfire.to app

* fixed file size

* Draft shell on md screen

* Draft small settings bar

* Add padding to dropdown menu

* WIP

* Create mobile settings nav

* Fix conferencing render

* Only display mobile settings nav

* Clean up my account section

* Clean up

* Remove old draft shell

* Remove old draft shell

* Implement changes from #3817

* Revise sidebar

* WIP

* Side navigation drawer

* Fix type error

* Fix lint problem

* Get rid of main top padding on main shell

* Fix e2e test

* Fix type error

* Remove unused imports

* Add back button function

* Update SettingsSidebarContainer.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: Kszemi <mkrzemien11@gmail.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-09-06 12:23:17 -06:00
Peer Richelsen 62ab3056a5 fixed dropdown component styling, added new shadow-dropdown (#4211) 2022-09-06 17:56:13 +00:00
Peer Richelsen f9d639b157 fixed app bar on mobile (#4209) 2022-09-06 17:05:16 +00:00
hexcowboy b30ab45612 fix mobile styling for rainbowkit gate (#4207) 2022-09-06 18:40:28 +02:00
Peer Richelsen 143279699a fixed subpage pills (#4204)
* fixed subpage pills

* nit
2022-09-06 11:06:39 +02:00
bbf22a29b0 New Crowdin translations by Github Action (#4202)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-06 10:54:21 +02:00
5ca2c0561c New Crowdin translations by Github Action (#4188)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-06 10:53:25 +02:00
Syed Ali Shahbaz addd58cca6 fixes dark mode piblic page (#4201) 2022-09-06 10:50:36 +02:00
Carina Wollendorfer dc6f8d1f63 V2 workflow improvements (#4070) 2022-09-05 23:29:00 -04:00
zomars dc68b608a0 Adds apps/installed to blacklist v2 2022-09-05 19:09:04 -06:00
zomars 6fdbadc94b Removed disconnected calendar notice 2022-09-05 19:09:04 -06:00
Alex van Andel 046dadbae2 Fixes labels for v2 nav being blank (#4190) 2022-09-05 18:40:27 -06:00
zomars d0c66a0a64 v1.9.3 2022-09-05 15:26:14 -06:00
zomars 0ea42faa57 Submodule sync 2022-09-05 15:25:41 -06:00
35459a046b feat: Migrating App Store to v2 (#3911)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Even Type move order handles

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* Starting migration

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Explore all apps section WIP

* Update packages/ui/v2/core/layouts/AppsLayout.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Interactive category list

* Moving stuff to pages/v2

* Latest changes

* Restoring uneeded changes

* Making v1 apps work

* Removing duplicated css util

* Update apps/web/middleware.ts

Co-authored-by: Omar López <zomars@me.com>

* Hiding categories for now

* Accomodating badges for app card

* Default for global apps, filtering tweaks

* Fixing types

* Reimplementing fixing types

* i18n + type fix

* Removing unneeded eslint exception

* Fixing tabs in app layout

* Commiting yarn.lock in case it helps

* Routing enabled category filter + responsive appcard

* Feat: v2 app store category/categories (#4126)

* Single category page

* Latest changes

* Applying feedback

* Migrates UpgradeToProDialog

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-05 15:22:28 -06:00
18d697436c Feat: Web3 Rainbowkit Integration (#4019)
* add new rainbow app and metadata

* add rainbowkit components

* add rainbow to event-type form

* create wallet connection ui

* verify signature when event is booked

* extract rainbow logic to app-store

* fix issues, dynamic import, theming

* skeleton, better api logic

* add gate logic to /[user]/book

* Fixes package.json

* Update yarn.lock

* Type fixes

Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-05 15:10:58 -06:00
Carina WollendorferandCarinaWolli faf62ac8e7 Design improvements for v2 security settings pages (#4087)
* fix password change design

* fix 2fa design

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-09-05 15:08:59 -06:00
Omar López 8653e8eea5 Adds banner to Opt-in to V2 UI (#4187) 2022-09-05 14:25:21 -06:00
49a379ec6c fix: use json.parse to get id (#4001)
* fix: use json.parse to get id

* fix: type error

* fix: add zod parse

* chore: remove type

Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-05 13:13:49 -06:00
52b2ce8774 V2.0 Shell - Progressive Rendering with Skeleton (#4138)
* Fix Routing

* Update up and down icons

* Add Shell Progressive loading

* Cleanup of custom loader

* Remove skeleton for heading and subtitle

* Replaces isI18nLoading for isLocaleReady

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-05 19:06:34 +00:00
10815c9541 Get user from token as required for magic login to work (#4163)
* Get user from token as required for magic login to work

* Update apps/web/pages/api/auth/[...nextauth].tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Linting

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-05 11:39:16 -06:00
Alex van Andel ebd4ce0340 Bugfix/typescript performance (#4073)
* next-env.d.ts should be generated as part of next build

* Removed next-env.d.ts from storybook

* Remove barrel imports from '@calcom/ui/v2/...' content

* Remove tabs barrel

* Further changes as the barrel for tabs is removed
2022-09-05 17:16:42 +01:00
Syed Ali Shahbaz 0e63996ee2 V2 select fixes (#4123) 2022-09-05 15:34:03 +00:00
Peer Richelsen 898c83d1ad added new VerticalDivider, using it in Event-types, fixed padding in app store (#4165)
* added new VerticalDivider, using it in Event-types

* fixed event-type app store empty screen padding and workflows padding

* centered emtpyscreen description

* made empty screen button secondary on app store

* fixed hide from profile on mobile

* squared dropdown on event-types
2022-09-05 15:15:26 +00:00
Peer RichelsenandAlex van Andel d0aaa4d83b fixed horizontal nav on mobile, hiding scrollbar (#4176)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-05 14:50:26 +00:00
github-actions[bot]andCrowdin Bot c610c73378 New Crowdin translations by Github Action (#4184)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-05 16:31:17 +02:00
8602a0a6e1 V2 Fixes (#4156)
* Remove shadow

* Empty screen

* V2 Create event type

* Fix switch not being right alligned

* Fix modal anatomy

* Fix layouts across app

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-05 16:23:18 +02:00
Peer Richelsenandkodiakhq[bot] 7b0d4f0f78 #4133 fixed tooltip positioning (#4136)
* fixed tooltip positioning

* fixed right side tooltip and z-index

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-05 12:49:20 +02:00
Peer Richelsen b0a1902ca3 fixed dark mode avatar border (#4161) 2022-09-05 12:27:40 +02:00
Peer Richelsen ae5030198c replaced gravatar default (#4158) 2022-09-05 10:23:39 +00:00
Peer Richelsen 8a2005ccf1 fixed search icon and tablet menu (#4139) 2022-09-05 10:02:21 +00:00
Peer Richelsen 1c90dcaa62 fixed campfire regex (#4149) 2022-09-04 22:30:35 +02:00
4ea29ed2ac #4141: Fixed stretched image in app detail page. (#4144)
Co-authored-by: Jeroen Reumkens <jeroen.reumkens@deptagency.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-04 22:25:32 +02:00
github-actions[bot]andCrowdin Bot 45bdfcfb7d New Crowdin translations by Github Action (#4147)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-04 22:24:44 +02:00
Jeroen ReumkensandJeroen Reumkens 93adf57d00 #4110: Made vertical tabs in bookings and event types pages sticky. (#4145)
Co-authored-by: Jeroen Reumkens <jeroen.reumkens@deptagency.com>
2022-09-04 14:59:16 +00:00
5e77b95e48 New Crowdin translations by Github Action (#4143)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-03 19:17:33 +02:00
Peer Richelsen dbca3ee780 fixed add a location button (#4137) 2022-09-03 19:14:30 +02:00
Peer Richelsen c9d384c397 removed bg behind app logo and made category icon rounded (#4142) 2022-09-03 19:14:02 +02:00
MrBirbandPeer Richelsen a213fa95f8 Delete ColorPalletGenerator.js (#4075)
I believe this is not used anywhere.

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-03 10:22:14 +02:00
1948455be0 wip: remove metamask app (#4049)
* wip: disable metamask app

* fix: remove dont comment

* fix: remove dont comment

* Update packages/app-store/index.ts

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

* Update packages/app-store/index.ts

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

* fix: bookingpage

* fix: remove web3Details zod

* removed unused web3

* Build fixes

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-02 17:55:12 -06:00
sean-brydon 015ed6d4f9 Public Booking Pages (#4063)
* Teams + /book

* Consitant hoverstate across event-type cards

* Fix darkmode hover on book a team member

* Fix mobile wrapping

* Fix mobile looking awful with long links

* Fix storybook

* Fix SB

* Phone Input darkmode

* Location radio styles darkmode

* Off Topic: NIT add disable guests

* Update highlights on /book and [user]/[type]

* Fix preview URL

* Fix hover state

* Fix spacing for locations
2022-09-02 21:16:36 +00:00
checkly[bot] 265af73ad0 [Checkly] adds "Cal.com Dashboard" code (#4134)
Co-authored-by: checkly[bot] <54914329+checkly[bot]@users.noreply.github.com>
2022-09-02 20:59:06 +00:00
46f2142e5f V2 for app setup pages (#4086)
* add v2 for app setup pages

* create v2 app setup page

* Build fixes

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-02 14:39:44 -06:00
zomars bcb7861a04 Unleash full parallel e2e power 2022-09-02 13:39:45 -06:00
zomars 52289a5cb5 Adds deprecation notice for Loader 2022-09-02 13:39:45 -06:00
Peer Richelsen f353da625e /booking v2 fixes (#4117)
* fixed wipe my cal button

* fixed booking buttons

* new buttons for request reschedule

* removed "yet" from empty screen in booking
2022-09-02 21:30:06 +02:00
26b771064d V2.0 - Routing Forms and Shell 2.0 everywhere (#3902)
* Add duplicate form support

* Fix duplication logic

* Change to feathericons everywhere and other fixes

* Dont allow routes for fallback route

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Fix all TS issues

* Fix tests

* Troubleshoot container + Active on count

* Support routing using query params

* Improve mobile

* NITS

* Fix padding on input

* Support multiselect in router endpoint

* Fix the issue where app goes in embed mode after viewing embed once

* Fix icons

* Add router url tests

* Add Responses download and form toggling tests

* Add required validation test

* Change Icons everywhere

* App typeform app

* Improvements in cli

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Add typeform how-to-use page

* Add typeform how-to-use page and screenshots

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Fix TS error

* Add missing image

* Update CliApp.tsx

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Major locations cleanup, 10s of bug fixes and app-store improvements

* Fix missing pieces

* More fixes

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* more fixes

* EventType Team page WIP

* Fix embed

* Use new Shell

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Get form-edit page working

* Get route-builder page working

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Get UI as per designs for form-edit

* Make route-builder upto date with design

* Add no responses banner

* Update forms list as per designs

* Button shouldnt decide where it would be positioned, users of it might have different requirements

* A single select box in a row(when no other select boxes are present) wasnt taking the correct width in comparison to when it had other select boxes

* Small missing pieces

* Revert console

* Revert api

* Fixes

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* Fix TS errors

* Add missing import

* Fix CLI

* Add a default placeholder

* Remove hardcoded daily:integrations

* Fix message for payment page

* Revert api and console to main

* Update README

* Fix TS errors

* Fix Lint warnings

* Fix Tests

* Streamline actions and make them easy to manage

* A much more simplified approach to implementing actions

* Fix embed

* Fix most TS errors

* Fix more TS errors

* Reduce TS errors to zero

* Fix tests

* Fix UI

* Fix UI

* Self review fixes

* TS failures caught merge issues

* Security hardening

* Use V2 Shell everywhere

* Add missing file

* Problems created by new shell fixed

* Fix Shell

* Fix Routing Form Card up and down positons

* Fix Embed and other design fixes

* Fix dropdown old event-types

* Fix type errors

* Fix allowed chek

* Fix dropdown not closing on clicking EMbed button

* Fix dropdown not closing on embed button

* Fix event-type button group layout

* Add label for switch

* Fix dropdown in mobile mode

* Remove useless comments

* Login with pro for tests

* Remove bg gray till App-Store pages are revamped

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-09-02 19:00:41 +00:00
f3be103456 feat: #3921 Added v2 design for booking details. (#4118)
Co-authored-by: Jeroen Reumkens <jeroen.reumkens@deptagency.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2022-09-02 15:12:58 +02:00
0e54f755e3 New Crowdin translations by Github Action (#4125)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-02 15:10:19 +02:00
9b9a16b847 New Crowdin translations by Github Action (#4121)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-02 13:43:00 +02:00
Peer Richelsen 31abf01724 added "add another calendar" to event-types detail in advanced (#4122) 2022-09-02 13:42:39 +02:00
Lennart GastlerandPeer Richelsen 11b52c839c fix: add extra word-break for chromium (#4080)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-02 13:14:12 +02:00
github-actions[bot]andCrowdin Bot 7d7e4464d2 New Crowdin translations by Github Action (#4068)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-09-02 13:11:48 +02:00
sean-brydon 03a9996c84 Tidy up on event-types + NITS (#4119)
* Apply correct padding to switch

* Make gray badges less eye catching

* Update description text color

* Tidy up setup tab

* Use V2 dialog on edit location

* use V2 select

* Menu Item component + fix menuitem

* Fix dropdown alignment
2022-09-02 13:10:55 +02:00
Omar López d27b7ab2c4 One playwright config to rule them all (#4072) 2022-09-01 20:00:48 -06:00
Peer RichelsenandCarina Wollendorfer b09d727d3f small fixes to switch (#4067)
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
2022-09-01 18:48:25 -04:00
0db1b3f023 Fixes 400 being thrown for NaN on disabling seats (#3945)
* Fixes 400 being thrown for NaN

* remove log

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-01 10:37:47 -06:00
Peer RichelsenandAlex van Andel a97bfbb1ce added lottie-react, added <Logo animated> for success page (#4083)
* added lottie-react, added <Logo animated> for success page

* Fixes lint issues

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-09-01 13:37:21 +01:00
Peer Richelsen d87ddef135 fixes dark mode for success (#4081) 2022-09-01 13:18:02 +02:00
Syed Ali ShahbazandPeer Richelsen c455639ff4 Feat/v2 daterangepicker (#4002)
* fixes minimum notice label

* adds story for daterange picker

* imports styles from global

* adds daterangepicker type inside packages types folder

* wraps tooltip with tooltip provider

* improvements

* further fixes

* fixes NIT

* match design specs

* adds space between input and calendar

* NITs

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-09-01 10:09:08 +00:00
Peer Richelsen d5b7195d67 fixed dark mode skeleton on public page (#4064) 2022-09-01 10:22:49 +01:00
Omar Lópezandkodiakhq[bot] fe67b99096 Refactors google calendar service (#3933)
* Refactors google calendar service

* Update CalendarService.ts

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-09-01 04:42:53 +00:00
Udit Takkar 84cff3613a feat: reschedule workflow added (#3996) 2022-08-31 23:09:34 +00:00
zomars 4308138170 Update yarn.lock 2022-08-31 15:16:44 -06:00
HashenandOmar López d876688325 Bump tsdav from 2.0.2 to 2.0.3 (#3632)
Co-authored-by: Omar López <zomars@me.com>
2022-08-31 15:05:33 -06:00
f4fe91396f Improve 2fa: ask for code before account removal and 2fa disabling (#3817)
* fix conflicts

* fix remove separate function and call mutation directly

* feat: add new react-otp-input to enable 2fa flow

* fix: comment out

* fix: remove next-auth 4.9.0 from yarn.lock

* fix: delete account test fill password before submit

* fix: test delete accc

* fix typo in delete acc test

* Update apps/web/components/security/EnableTwoFactorModal.tsx

Co-authored-by: Omar López <zomars@me.com>

* feat: remove react-otp-input reuse TwoFactor

* feat: add center props to TwoFactor

* fix: no v2

* feat: disable 2fa requires 2fa api

* feat: make 2fa required to disable 2fa

* fix: FormEvent instead of SyntheticEvent

* fix: types

* fix: move disable 2fa form to fully use RHF

* fix     if (e) e.preventDefault();

* feat: fix remove account

* fix: remove react-otp-input types

* fix: separate onConfirm to add to form handleSubmit

* fix: types e:SyntethicEvent

* fix: types

* fix: import packages lib not web lib

* Update apps/web/components/security/EnableTwoFactorModal.tsx

Co-authored-by: Omar López <zomars@me.com>

* Update apps/web/components/security/EnableTwoFactorModal.tsx

Co-authored-by: Omar López <zomars@me.com>

* fix: no import from web

* fix: import

* fix: remove duplicate FormEvent

* fix: upgrade ErrorCode imports

* fix profile types totpCode not optional

* fix: build pass

* fix: dont touch test delete-account

* fix: type

* fix: add data-testid to password field

* fix: conflicts w syncServices

* Build fixes

* Fixes delete account e2e test

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-31 14:57:53 -06:00
58c4c894fd fix: update rejectOnNotFound -> find(Fist|Unique)OrThrow (#3829)
* fix: update rejectOnNotFound -> find(Fist|Unique)OrThrow

* fix: add back custom errohandling

* feat: handle notfounderror in getServerErrorFromUnknown

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: Omar López <zomars@me.com>
2022-08-31 13:44:47 -06:00
+2 eeabb53c82 V2 Workflows (#4047)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* add Test action button + UI improvements

* add test action functionality

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* add confirmation dialog before sending SMS

* code clean up

* show error message if test action fails

* disable test action button in edit mode

* fixes SMS testing

* use updated values

* fix wrongly updated data in useEffect

* fix typo

* code clean up

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* setup folders for v2

* add lost translations from merge

* add all files to v2 + redesign /workflows

* use custom template as default template

* add first version of v2 for workflow editing page

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* use fi icon for down arrow

* add v2 shell

* add trigger badge

* Even Type move order handles

* fix save button

* enable editing of workflow name

* improve delete workflow functionality

* adjust empty screen

* make trigger start with uppercase

* change trash icon

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* create component for time and timeUnit input/dropdown

* add workflows to v2 early access middleware

* fix type issues

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* adjust delete and edit button

* create custom empty screen for worklows

* add workflow examples to empty page

* add loading state to button when creating first workflow

* Show action as workflow name when no name exists

* if no input leave name empty when updating workflow

* use reminder template when creating workflow

* improve time unit dropdown

* Remove unused component

* Fix typecheck

* add loading state to new workflow button

* add label before action dropdown

* fixing badges in worflow list

* use lighter color for untitled workflows

* fix not showing nr of active eventtypes in workflow list

* add workflows to event types

* implement v2 desing for AddActionDialog

* improve phone input

* rounded borders for phoneInput in add action dialog

* improve message input

* fix mobile view for editing page

* use md breakpoint for mobile view

* finish workflows in event type settings

* code cleanup

* code cleanup

* fix bug in testing workflow action

* add v2 design for addition inputs as variables dialog

* add V2 design for add variable dropdown

* add notification icons to trigger badge

* improve mobile version of workflows in eventtypes

* remove ring from time before input

* fix bug when workflow has no steps

* Final UI improvements/fixes

* code clean-up

* code clean-up

* code clean-up

* use v2 design for license required

* fix translation issues

* fix adding variables in different language in old design

* limit for pro users only for now

* fix import

* fix mobile view for empty screen

* ues destructive button color for deleting workfow

* remove padding at button of creation dialog

* V2 Settings - Security View (#4018)

* Create change password screen

* Add two factor auth screen

* Add two factor auth screen

* Remove header file

* Updates middleware and rewrites

* Adds Meta component to handle layout headings/metadata (#4021)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>

* fix: rate limit auth (#3820)

* fix: rate limit auth

* fix: replace lru-cache w memory-cache

* remove comments

* fix: yarn.lock

* fix: remove changes yarn lock

* fix: add missing EOL empty liune

* fix: move rate limiter so it kicks the last, limit to 10 tries per minute

* fix: move limiter w rest of code

* test: trying fix onboardong

* fix: undo changes in globalSetup.ts

* test: fix disable login for onboarding

* fix: use username instead of email for token check

* fix: tests

* fix: don't run on test

* fix: add missing comma

* fix: remove uniqueTokenPerInterval

* fix: add errorcode to packages lib auth

* Update packages/lib/rateLimit.ts

fix: improve readability

Co-authored-by: Omar López <zomars@me.com>

* Update packages/lib/rateLimit.ts

fix: no unnecessary any

Co-authored-by: Omar López <zomars@me.com>

* Update packages/lib/rateLimit.ts

fix: improve readability

Co-authored-by: Omar López <zomars@me.com>

* fix: rename interval -> intervalInMs

* fix: check user.email not username which could be empty

* fix: rateLimit update all naming

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* Adds deprecation comments

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Agusti Fernandez Pardo <6601142+agustif@users.noreply.github.com>
Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
2022-08-31 13:42:37 -06:00
6c3dcc2fbf fix: lark calendar refresh token bug (#4066)
Co-authored-by: chengcheng.frontend <chengcheng.frontend@bytedance.com>
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-31 19:19:30 +00:00
zomars 397d47b4b5 Clean up auth state after all E2E tests are done 2022-08-31 12:28:29 -06:00
zomars e020bb9758 Uncap local e2e testing 2022-08-31 11:30:05 -06:00
zomars dbbf77f21a Revert "Fixes type error (#4065)"
This reverts commit 19ae065f68.
2022-08-31 11:05:30 -06:00
sean-brydon 19ae065f68 Fixes type error (#4065) 2022-08-31 17:12:44 +02:00
Hariom Balharaandkodiakhq[bot] bb0ff5503a Fix locations listing in v2 (#4062)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-31 14:11:36 +02:00
sean-brydon e17c463890 V2 General Fixes (#4038) 2022-08-31 11:13:27 +00:00
Hariom Balharaandkodiakhq[bot] f5e394bb57 Add back enabledDateButton and disabledDateButton UI custom styling for embed (#4059)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-31 09:47:23 +00:00
Hariom Balhara 2414cacabb Fix routing forms logo (#4058) 2022-08-31 09:26:16 +00:00
Peer Richelsen dd24ef4946 added translation for meeting ended webhook (#4057) 2022-08-31 10:30:05 +02:00
a3eeb9e3a3 Fix Zapier setup page (#4054)
* fix zapier setup page

* update app description

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-31 09:43:40 +02:00
b151ccd4c6 prevent from save doubled subscriber url (#3811)
Co-authored-by: Adam Garbowski <adamgarbowski90@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2022-08-31 03:41:23 +00:00
zomars 0c8847fb87 Restores linting/type-check locally 2022-08-30 15:24:17 -06:00
b8b1b9a6d0 fix: rate limit auth (#3820)
* fix: rate limit auth

* fix: replace lru-cache w memory-cache

* remove comments

* fix: yarn.lock

* fix: remove changes yarn lock

* fix: add missing EOL empty liune

* fix: move rate limiter so it kicks the last, limit to 10 tries per minute

* fix: move limiter w rest of code

* test: trying fix onboardong

* fix: undo changes in globalSetup.ts

* test: fix disable login for onboarding

* fix: use username instead of email for token check

* fix: tests

* fix: don't run on test

* fix: add missing comma

* fix: remove uniqueTokenPerInterval

* fix: add errorcode to packages lib auth

* Update packages/lib/rateLimit.ts

fix: improve readability

Co-authored-by: Omar López <zomars@me.com>

* Update packages/lib/rateLimit.ts

fix: no unnecessary any

Co-authored-by: Omar López <zomars@me.com>

* Update packages/lib/rateLimit.ts

fix: improve readability

Co-authored-by: Omar López <zomars@me.com>

* fix: rename interval -> intervalInMs

* fix: check user.email not username which could be empty

* fix: rateLimit update all naming

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-30 13:58:35 -06:00
f5c1c76f0a V2 Settings - Security View (#4018)
* Create change password screen

* Add two factor auth screen

* Add two factor auth screen

* Remove header file

* Updates middleware and rewrites

* Adds Meta component to handle layout headings/metadata (#4021)

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-30 13:46:52 -06:00
Zach Waterfieldandkodiakhq[bot] e66050a414 Improve the README development setup steps around environment variables (#4034)
* Set the NEXTAUTH_URL in the .env example

* Add a .env step to the README development setup steps.

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-30 12:44:21 -06:00
Deepak Prabhakara 1a81459e28 Fix SAML login (#4037)
* after first login the user is read from the db and hence we need to inspect the `emailVerified` attribute as well.

* fixed mapping documentation for SAML, the current mapping is not right and is causing confusion
2022-08-30 12:25:24 -06:00
Cheng CHENGandchengcheng.frontend ad8d0a4e77 fix: lark calendar get app access token bug (#4043)
Co-authored-by: chengcheng.frontend <chengcheng.frontend@bytedance.com>
2022-08-30 13:08:29 -04:00
sean-brydon fe12a83898 Fixing padding + heading sizes (#4032)
* Fixing padding + heading sizes

* Fix title position
2022-08-30 15:47:43 +02:00
sean-brydon 7d611c5527 Border color - brand color - mobile 1 colum times (#4025) 2022-08-30 13:51:08 +02:00
Alex van Andel 0bd8c23be7 Proposal to turn off eslint during 'yarn / next build' (#4027) 2022-08-30 13:50:34 +02:00
Alex van Andel fdc8a839b4 Fix linting error (#4026) 2022-08-30 13:46:03 +02:00
3da3e6ec38 feat: Adds new v2 design for app detail page. Fixes #3779 (#3997)
* feat: Adds new v2 design for app detail page. Fixes #3779

* fix: Made app images 90% width on mobile to show indication for scrolling. #3779

* Update apps/web/components/v2/apps/App.tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

Co-authored-by: Jeroen Reumkens <jeroen.reumkens@deptagency.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Peer Richelsen <peer@cal.com>
2022-08-30 11:37:40 +02:00
sean-brydon fb3c481235 V2 colors - Public Booking (#4022)
* V2 colors

* Fix border right

* Fixing spacing
2022-08-30 10:56:30 +02:00
alannnc 3527c5126a Added Syntax error case and also default error returning (#4015) 2022-08-29 18:05:35 -06:00
d75a8910f6 Update all Yarn dependencies (2022-08-17) (#3887)
* Update all Yarn dependencies (2022-08-17)

* Fix package mismatches

* Submodule sync

* Type fixes

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-29 17:55:27 -06:00
Omar Lópezandkodiakhq[bot] 037410aea7 One jest to rule them all (#3957)
* WIP

* Consolidates jest deps

* Test fixes

* Moves jest to root

* Test fixes

* Update CalendarService.test.ts

* Cleanup

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-29 22:33:53 +00:00
zomars 54bd1436b1 v1.9.2 2022-08-29 16:20:20 -06:00
zomars a262d261a7 Submodule sync 2022-08-29 16:20:06 -06:00
e4e4ec5ffc Availability and booking info text format fixes (#4000)
* Recurring info format

* More mismatch visual bugs when booking

* More tweaks

* Prettier

* Prettier cont

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-29 13:01:45 -03:00
00c00a9aee fix: add required property on input (#3934)
* fix: add required property on input

* chore: remove console

* fix: add check in /api/book for custom inputs

* chore: var name

* wip:try zod

* fix: change zod validation

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-29 13:04:22 +00:00
Peer Richelsen 85cc62d0cb temp remove <Tips> card from sidebar till 2.1 (#4010) 2022-08-29 14:04:39 +02:00
Udit TakkarandPeer Richelsen ac50492fbc fix: add warn and trash icon (#4008)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-29 13:57:01 +02:00
4b771a5bde fixing cursor for Default badge svg, from text type to default (#3994)
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-28 18:31:56 +02:00
944f4dc43b fix: pass recurring count value (#3844)
* fix: pass recurring count value

* fix: show dates for pending booking

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
2022-08-27 10:12:38 -03:00
Leo Giovanetti cfe7c7a5b3 Fixing CalendarService tests (#3993) 2022-08-26 17:21:12 -06:00
Edgar Allan Glezandalannnc d1c5268ef0 Feature 3976/fix label (#3992)
* changing username label placeholder to Apple ID text in apple calendar setup

* reset yarn.lock

* remove translate function for apple id label, not necessary

Co-authored-by: alannnc <alannnc@gmail.com>
2022-08-26 16:49:38 -06:00
02ac593ebf Migrate legacy api endpoints to tRPC II (#3865) (#3991)
* Migrate legacy api endpoints to tRPC II (#3865)

* fix: delete api route /api/availability/day

* fix: delete api route /api/availability/eventtype (#3573)

* fix: delete api route /api/event-type (#3573)

* migrate /api/book/confirm to viewer.bookings.confirm

* Merge branch 'main' into pr/3865

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

* Import fixes

* Import fixes

Co-authored-by: mohammed hussam <52914487+hussamkhatib@users.noreply.github.com>
Co-authored-by: hussamkhatib <hussamkhatib@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-26 15:58:08 -06:00
1d927a8b33 chore: Sync Services to update external tools (#3814)
* WIP close.com app

* Removing leaked dev key (now invalid)

* Misspelled env variable

* Making progress still WIP

* Progress + tests

* Final touches

* More unit tests

* Finished up tests

* Merge main

* Removing unneeded stuff + submodules

* Removing static props, fields fix

* Removing unneeded stuff p2

* Commenting

* Refactoring Close.com Calendar Service + initial structure

* Progress con CloseComService

* Standarizing APIs

* Zodifying

* Expanding sync services

* Sendgrid Sync Service

* using own request for sendgrid + debug logs

* Making get last booking work for console

* Helpscout dynamic app API

* Standarizing calls + adding call from booking creation

* Strategy change for last booking

* Strategy change for last booking on help scout api

* Fixing failing build

* Implementing user deletion

* Fix linting + slight cleaning

* Undoing eslint disable

* Removing more unsupported eslint properties

* Closecom as non-standard sync service

* Finishing closecom lead operations

* Fixing lint

* Guarding app from sync services

* Reverting submodules

* Applying PR feedback

* Reverting API to be plain handler

* Cleaning notes

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-26 15:10:12 -06:00
sean-brydonandPeer Richelsen 090a977f72 AppsTab UX + fixes warptext on horizontal tabs (#3966)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-26 13:04:45 -06:00
2d3a6fb4ca fix: add team model in prisma middleware (#3947)
* fix: add team model in prisma middleware

* refactor: move to getParsedResults function

* fix: add eventtype

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-26 12:59:58 -06:00
974ff03127 REPLY_TO in hello@cal.com emails (#3959)
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: hustle-ps <grace.devolop@gmail.com>
Co-authored-by: Júlio Piubello da Silva Cabral <julio.piubello@gitstart.dev>
Co-authored-by: Matheus Benini <matheus_benini@hotmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-26 12:51:32 -06:00
4ef666a610 Zoom/Hubspot Tests with MSW mocking of requests initiated from Next.js server (#3210)
* Add code from previous PR

* Remove env variables from wrong place

* Fix tests

* Remove dead code

* Package.json updates

* Fix eslint error

* Fix issue due to conflict resolution

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-26 12:44:02 -06:00
Alex van Andel e0744a4857 Fixed a typo in notifications->showToast & updated all imports (#3990) 2022-08-26 12:13:49 -06:00
fac99c3e9b Disable broken calendar email (#3946)
* Disable broken calendar email

* Add comment

* Apply suggestions from code review

Co-authored-by: alannnc <alannnc@gmail.com>

* Apply suggestions from code review

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: alannnc <alannnc@gmail.com>
2022-08-26 12:12:47 -06:00
Alex van Andel 006badc3b5 Backported 973e0a3..6ad0e23 (#3943) 2022-08-26 12:07:44 -06:00
Alex van Andel 19e9e0083e Static images through webpack copy (#3986)
* Static images through webpack copy

* Turn image optimisation off - not needed tbh
2022-08-26 10:31:55 -06:00
Peer Richelsen 19fe931f4b fixed file size campfire (#3985)
* added campfire.to app

* fixed file size
2022-08-26 14:46:15 +02:00
Peer Richelsen 0856339e3a added campfire.to app (#3984) 2022-08-26 11:35:19 +00:00
Omar Lópezandkodiakhq[bot] cf321496d4 Adds deprecation notice to QueryCell (#3977)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-26 09:32:58 +00:00
Hariom Balhara c6e54d9d9d Improve CLI App Help Text (#3982) 2022-08-26 09:33:00 +02:00
b00402f429 Button to test a workflow action (#3873)
* add Test action button + UI improvements

* add test action functionality

* add confirmation dialog before sending SMS

* code clean up

* show error message if test action fails

* disable test action button in edit mode

* fixes SMS testing

* use updated values

* fix wrongly updated data in useEffect

* fix typo

* code clean up

* fix UI issue in mobile view

* small design fix

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-26 01:04:44 +00:00
6c86317081 AppStore CLI: Making video app creation a breeze with major cleanup of locations code throughout (#3825)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Add Embed ModalBox for routing forms

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Add duplicate form support

* Fix duplication logic

* Change to feathericons everywhere and other fixes

* Dont allow routes for fallback route

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Fix all TS issues

* Fix tests

* Troubleshoot container + Active on count

* Support routing using query params

* Improve mobile

* NITS

* Fix padding on input

* Support multiselect in router endpoint

* Fix the issue where app goes in embed mode after viewing embed once

* Fix icons

* Add router url tests

* Add Responses download and form toggling tests

* Add required validation test

* Change Icons everywhere

* App typeform app

* Improvements in cli

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Add typeform how-to-use page

* Add typeform how-to-use page and screenshots

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Fix TS error

* Add missing image

* Update CliApp.tsx

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Major locations cleanup, 10s of bug fixes and app-store improvements

* Fix missing pieces

* More fixes

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* more fixes

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Revert console

* Revert api

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* Fix TS errors

* Add missing import

* Fix CLI

* Add a default placeholder

* Remove hardcoded daily:integrations

* Fix message for payment page

* Revert api and console to main

* Update README

* Fix TS errors

* Fix Lint warnings

* Fix Tests

* Fix conflict issues

* Fix conflict issues

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-25 18:48:50 -06:00
87cce8eab6 2.0 Settings / My Account {View} (#3874)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Create my account folder

* Add profile section

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* WIP

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Finish profile fields

* Show toast on success

* General tab WIP

* Even Type move order handles

* Add switching of destination calendar

* List calendar and delete

* Render empty screenwhen no calendars

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Transfer to SSR

* Appearance screen made

* V2 image uploader

* WIP appearance page

* Remove unnecessary data from viewer.me

* Add profile translations

* Add translations to general page

* Add calendar switch

* Add calendar switch

* Add translations to appearance page

* Clean up conferencing page

* Settings sidebar fixes

* Updates middleware

* Update SettingsLayout.tsx

* Settings layout improvements

* Type fix

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-25 18:11:41 -06:00
11dc9c668e Adding continue button to connectCalendar on getting-started view (#3971)
* Adding continue button to connectCalendar view getting-started

* Fixing extra space

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
2022-08-25 21:27:37 +00:00
github-actions[bot]andCrowdin Bot 8f6ba440b7 New Crowdin translations by Github Action (#3954)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-25 22:51:58 +02:00
Omar LópezandLeo Giovanetti 18c949207e Fixes CLS when loading Avatars (#3973)
* Fixes CLS when loading Avatars

* Update packages/ui/v2/core/Avatar.tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

Co-authored-by: Leo Giovanetti <hello@leog.me>
2022-08-25 19:35:01 +00:00
Omar López b84c8d9e82 Update PULL_REQUEST_TEMPLATE.md 2022-08-25 12:29:19 -06:00
alannnc 4feda21d22 Hidding import features from other services (#3970) 2022-08-25 20:25:00 +02:00
KszemiandPeer Richelsen 45f16333a8 fixed slots availability by fixing buffertime (#3756)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-25 18:57:15 +02:00
9c3cea512f Fixing back reference to recurring event when rescheduled (#3967)
* fix: pass recurring count value

* fix: show dates for pending booking

* Restoring recurringEventId on reschedule

* Reverting other changes from a different PR

Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-08-25 15:18:03 +00:00
Syed Ali Shahbaz 7f94ce0605 Fix availability free-busy data pull, location change and status in CALDAV | new branch (attempt#2) (#3958) 2022-08-25 14:48:30 +05:30
alannncandOmar López 1b541ff214 Fix/connected calendar component (#3956)
* Fix for displaying connected calendars alert with test

* Fix default calendar display string when externalId its too long

* Update apps/web/components/ui/LinkText.tsx

Co-authored-by: Omar López <zomars@me.com>

Co-authored-by: Omar López <zomars@me.com>
2022-08-24 19:44:14 -06:00
zomars 5950b62b02 Create add-PRs-to-project.yml 2022-08-24 16:46:43 -06:00
436f88a48e V2 Main (#3549)
* Fix breadcrumb colors

* HorizontalTabs

* Team List Item WIP

* Horizontal Tabs

* Cards

* Remove team list item WIP

* Login Page

* Add welcome back i118n

* EventType page work

* Update EventType Icons

* WIP Availability

* Horizontal Tab Work

* Add build command for in root

* Update build DIr/command

* Add Edit Button + change buttons to v2

* Availablitiy page

* Fix IPAD

* Make mobile look a little nicer

* WIP bookingshell

* Remove list items from breaking build

* Mian bulk of Booking Page.

* Few updates to components

* Fix chormatic feedback

* Fix banner

* Fix Empty Screen

* Text area + embded window fixes

* Semi fix avatar

* Troubleshoot container + Active on count

* Improve mobile

* NITS

* Fix padding on input

* Fix icons

* Starting to move event types settings to tabs

* Begin migration to single page form

* Single page tabs

* Limits Page

* Advanced tab

* Add RHF to dependancies

* Most of advanced tab

* Solved RHF mismtach

* Build fixes

* RHF conditionals fixes

* Improved legibility

* Major refactor/organisation into optional V2 UI

* Portal EditLocationModal

* Fix dialoug form

* Update imports

* Auto Animate + custom inputs WIP

* Custom Inputs

* WIP Apps

* Fixing stories imports

* Stripe app

* Remove duplicate dialog

* Remove duplicate dialog

* Fix embed URL

* Fix app toggles + number of active apps

* Fix container padding on disabledBorder prop

* Removes strict

* EventType Team page WIP

* Fix embed

* NIT

* Add Darkmode gray color

* V2 Shell WIP

* Fix headings on shell V2

* Fix mobile layout with V2 shell

* V2 create event type button

* Checked Team Select

* Hidden to happen on save - not on toggle

* Team Attendee Select animation

* Fix scheduling type and remove multi select label

* Fix overflow on teams url

* Even Type move order handles

* Fix Embed TS errors

* Fix TS errors

* Fix Eslint errors

* Fix TS errors for UI

* Fix ESLINT error

* added SidebarCard for promo to v2 and storybook (#3906)

Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Tooltip Provider - Wrapper due to dep upgrade

* public event type list darkmode

* V2 Color changes to public booking

* Remove unused component

* Fix typecheck

* Removed extra buttons on create ET dialog

* ET edit page refactoring

* Avoids form wrapping the whole Shell

* Nitpicks

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Julian Benegas <julianbenegas99@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
2022-08-24 14:18:42 -06:00
zomars c17e949cd6 Implements quick ip banlist
Debugs IP banlist

Adds explainer for getIP util

Adds collect-events to middleware filter

Fixes middleware
2022-08-24 10:57:23 -06:00
github-actions[bot]andCrowdin Bot b88f0617d8 New Crowdin translations by Github Action (#3935)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-24 13:41:51 +02:00
Peer Richelsen 6413bb399e hide desktop download link on tablet and mobile (#3939) 2022-08-24 12:38:43 +02:00
bfe780e0af fix add endIconClassName in button (#3893)
* fix add tooltip provider to tooltip

* fix: add endIconClassNames support for button as startIcon has

* fix: undo tooltip provder

Co-authored-by: Agusti Fernandez Pardo <git@agusti.me>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-24 08:37:46 +00:00
zomars 4e73c4f7fb v1.9.1 2022-08-23 09:23:08 -07:00
f4ea385c7f Fixes collective availability for teams with overlapping day timezones (#3898)
* WIP

* Fix for team availability with time offsets

* Prevent empty schedule from opening up everything

* When no utcOffset or timeZone's are given, default to 0 utcOffset (UTC)

* timeZone should not be part of getUserAvailability

* Prevents {days:[X],startTime:0,endTime:0} error entry

* Added getAggregateWorkingHours() (#3913)

* Added test for getAggregateWorkingHours

* Timezone isn't used here anymore

* fix: developer docs url (#3914)

* fix: developer docs url added

* chore : remove /

* chore : import url

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

* Test fixes

* Reinstate prisma (generate only) and few comments

* Test fixes

* Skipping getSchedule again

* Added await to expect() as it involves async logic causing the promise to timeout

* Test cleanup

* Update jest.config.ts

Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Zach Waterfield <zlwaterfield@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-22 23:53:51 +00:00
cb1d881cc0 fix: developer docs url (#3914)
* fix: developer docs url added

* chore : remove /

* chore : import url

Co-authored-by: Zach Waterfield <zlwaterfield@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-22 22:56:55 +02:00
+1 27c5bf9dbc Design issues on success page in some languages (#3900)
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Júlio Piubello da Silva Cabral <julio.piubello@gitstart.dev>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: Matheus Benini <matheus_benini@hotmail.com>
Co-authored-by: Grace Nshokano <grace.devolop@gmail.com>
Co-authored-by: Matheus Muniz <matheusmuniz100@hotmail.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: Murilo Amaral <87545137+MuriloAmarals@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-22 22:40:35 +02:00
github-actions[bot]andCrowdin Bot ef7dd5102b New Crowdin translations by Github Action (#3929)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-22 22:36:49 +02:00
github-actions[bot]andCrowdin Bot 0c3e309596 New Crowdin translations by Github Action (#3927)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-22 22:28:56 +02:00
Peer RichelsenandAlex van Andel 1b942c4003 redesigned cancel page to new design (#3923)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-08-22 19:48:33 +00:00
b328527434 fix/auto-connect-calendar-3582 (#3891)
* Added alert when there isn't default calendar connected

* Add default calendar externalId to select placeholder

* Fix typos

* Fixes prisma import

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-22 19:34:28 +00:00
Omar López 662b437a18 Merge branch 'production' into main 2022-08-22 10:32:25 -07:00
github-actions[bot]andCrowdin Bot e7f1413ed8 New Crowdin translations by Github Action (#3926)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-22 17:09:42 +02:00
github-actions[bot]andCrowdin Bot 071b20b6ec New Crowdin translations by Github Action (#3924)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-22 16:09:29 +02:00
github-actions[bot]andCrowdin Bot bf6dd6cb32 New Crowdin translations by Github Action (#3909)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-22 12:59:20 +02:00
Peer Richelsen c44e444271 Revert " cancel booking new design added" (#3922)
This reverts commit a06c564517.
2022-08-22 12:40:41 +02:00
Udit Takkar a06c564517 cancel booking new design added (#3660)
* feat:  cancel booking new design added

* style: add space-y in button

* style: ui fixed for recurring booking

* fix: scroll in recurring event and use translation

* style: text 2xl instead of text-[24px]

* fix: typo, spacing

* fix: replaced multiple h2 tags with div

* fix: padding and Icon name
2022-08-22 12:32:06 +02:00
Julian Benegas 02b5a2bc1f Revert "adjust react version"
This reverts commit 6e161da35b.
2022-08-19 13:23:34 -03:00
Julian Benegas 6e161da35b adjust react version 2022-08-19 13:22:07 -03:00
github-actions[bot]andCrowdin Bot b257cdbf1e New Crowdin translations by Github Action (#3897)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-18 20:18:03 +02:00
zomars 9de723d557 Sync submodules 2022-08-18 11:54:58 -06:00
zomars 081d5ae9c8 NEXTAUTH_DOMAIN isn't used 2022-08-18 11:53:29 -06:00
cddca2b10d New Crowdin translations by Github Action (#3890)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-18 18:10:03 +02:00
Peer Richelsen 6ed0e5e281 use default cursor on desktop (#3876) 2022-08-17 22:50:25 +02:00
github-actions[bot]andCrowdin Bot 1fd8d50e52 New Crowdin translations by Github Action (#3878)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-17 22:50:01 +02:00
Peer Richelsen 5206a37fe4 temporally removed missing calendar badge on event-types (#3889) 2022-08-17 13:51:45 -06:00
Peer Richelsen 025019f789 Update [uid].tsx (#3888) 2022-08-17 19:32:46 +01:00
zomars d58bd02cab Submodule sync 2022-08-17 11:41:08 -06:00
b8acf1e180 Update all Yarn dependencies (2022-07-29) (#3599)
* Update all Yarn dependencies (2022-07-29)

* Adds syncpack config

* Fixes mismatches

* Update yarn.lock

* RRule fixes

* Locking dayjs to fix build

* Type fixes

* Fixes mismatches

* Submodule sync

* Update yarn.lock

* Update event.ts

* Conflict fixes

* Fixes prisma warnings

* Liting

* Upgrade next, zod

* Prevents articfact overwriting

* Yarn fixes

* Jest fixes

* Submodule sync

* Formatting

* Submodule sync

* Adds provider for react-tooltip

* Removed dotenv-cli

* Readds dotenv-cli

* Skips getSchedule tests

Until prisma is mocked properly

* Fixes

* Revert prisma seed script

* E2E fixes

* test

* Removed deprecated req.page in middleware

* Make tests stable

* Unskip getSchedule tests

* fixed 404 logo on cal video (#3885)

* Removed PW aliases as aren't needed anymore

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-17 11:38:21 -06:00
Peer Richelsen d8fab68edd fixed 404 logo on cal video (#3885) 2022-08-17 16:59:00 +02:00
Hariom Balhara 592d46f758 Fix desktop app link (#3883) 2022-08-17 11:07:19 +02:00
Alex van Andelandzomars a331d02668 Hotfix/dos mitigation attempt error configuration (#3879)
* Fixes 'Task timed out after 60.03 seconds'

* DDoS rewrite fixes

Co-authored-by: zomars <zomars@me.com>
2022-08-16 17:43:01 -06:00
Syed Ali Shahbaz 73e38384e2 hotfix dynamic issue (#3864) 2022-08-16 17:43:01 -06:00
Alex van Andelandzomars f5b5150cf3 Hotfix/dos mitigation attempt error configuration (#3879)
* Fixes 'Task timed out after 60.03 seconds'

* DDoS rewrite fixes

Co-authored-by: zomars <zomars@me.com>
2022-08-17 00:38:26 +01:00
zomars 7e0dbee2ca DDoS rewrite fixes 2022-08-16 16:28:19 -06:00
Syed Ali Shahbaz 46715a6cd4 hotfix dynamic issue (#3864) 2022-08-16 16:07:44 -06:00
Alex van Andelandzomars 1e5cb0bbd0 Attempt at redirect to 404 (#3877)
* Attempt at redirect to 404

404 should be able to handle the traffic no problem - better ideas welcome. Just a temp fix I imagine; we're not going to want to keep this nor can we expect the User-Agent to continue identifying the traffic source.

* Update next.config.js

Co-authored-by: zomars <zomars@me.com>
2022-08-16 16:02:04 -06:00
Alex van Andelandzomars 3a54ca2c95 Attempt at redirect to 404 (#3877)
* Attempt at redirect to 404

404 should be able to handle the traffic no problem - better ideas welcome. Just a temp fix I imagine; we're not going to want to keep this nor can we expect the User-Agent to continue identifying the traffic source.

* Update next.config.js

Co-authored-by: zomars <zomars@me.com>
2022-08-16 16:01:38 -06:00
zomars 79d37676fc Middleware rewrite shenanigans 2022-08-16 13:59:38 -06:00
zomars 4f76654813 Whitelist only cal domain as callbackUrls 2022-08-16 13:55:50 -06:00
zomars 6dcb0c43ab DDOS mitigation updates 2022-08-16 13:50:09 -06:00
Hariom Balhara cf9116b5bb Avoid DDOS (#3871) 2022-08-16 19:15:13 +02:00
github-actions[bot]andCrowdin Bot 4df54ef3d1 New Crowdin translations by Github Action (#3857)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-08-16 13:34:04 +02:00
Jake CooperandPeer Richelsen 82c98a8b7b Update Railway Template (#3862)
* Update Railway Template

* Update URL

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-08-16 11:30:56 +00:00
Peer Richelsen 0d7be1886e fixed iframe in lark suite, added lark contact info (#3866)
* fixed iframe in lark suite, added lark contact info

* Update _metadata.ts
2022-08-16 13:28:52 +02:00
Hariom Balharaandkodiakhq[bot] bc6c9e1b0a Hotfix: Embed - Fix issue in accessing sessionStorage in certain scenarios (#3851)
* Fixes issue when sessionStorage is not accessible in privacy focussed modes in various browsers

* Fix eslint errors

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-08-16 04:18:13 +00:00
mohammed hussamandhussamkhatib 732acb5b25 fix: remove redundant AND (#3833)
Co-authored-by: hussamkhatib <hussamkhatib@gmail.com>
2022-08-15 16:35:44 -06:00
Carina WollendorferandCarinaWolli 5b6818a3cc fixes issue with variables not working (#3859)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-08-15 16:32:37 -06:00
Carina WollendorferandCarinaWolli 497d4902af fixes issue with variables not working (#3859)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-08-15 16:32:11 -06:00
Udit Takkar 8c7579fede fix: padding of kBarTrigger (#3846) 2022-08-15 16:31:27 -06:00
4ce6b91a79 Close.com App (#3709)
* WIP close.com app

* Removing leaked dev key (now invalid)

* Misspelled env variable

* Making progress still WIP

* Progress + tests

* Final touches

* More unit tests

* Finished up tests

* Merge main

* Removing unneeded stuff + submodules

* Removing static props, fields fix

* Removing unneeded stuff p2

* Commenting

* Standarizing APIs

* Zodifying

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2022-08-15 20:45:15 +00:00
812 changed files with 45789 additions and 11813 deletions
+6 -1
View File
@@ -87,7 +87,6 @@ VITAL_REGION="us"
# Used for the Zapier integration
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/zapier/README.md
ZAPIER_INVITE_LINK=""
# *********************************************************************************************************
# - LARK
# Needed to enable Lark Calendar integration and Login with Lark
@@ -95,4 +94,10 @@ ZAPIER_INVITE_LINK=""
LARK_OPEN_APP_ID=""
LARK_OPEN_APP_SECRET=""
LARK_OPEN_VERIFICATION_TOKEN=""
# - WEB3
# Used for the Web3 plugin
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/web3/README.md
ALCHEMY_API_KEY=""
INFURA_API_KEY=""
# *********************************************************************************************************
+10 -5
View File
@@ -30,8 +30,6 @@ NEXT_PUBLIC_WEBAPP_URL='http://localhost:3000'
NEXT_PUBLIC_WEBSITE_URL='http://localhost:3000'
NEXT_PUBLIC_CONSOLE_URL='http://localhost:3004'
NEXT_PUBLIC_EMBED_LIB_URL='http://localhost:3000/embed/embed.js'
# Make sure you don't have .example.com as a value
NEXTAUTH_DOMAIN='localhost:3000'
# To enable SAML login, set both these variables
# @see https://github.com/calcom/cal.com/tree/main/packages/ee#setting-up-saml-login
@@ -48,13 +46,12 @@ PGSSLMODE=
# @see: https://github.com/calendso/calendso/issues/263
# @see: https://next-auth.js.org/configuration/options#nextauth_url
# Required for Vercel hosting - set NEXTAUTH_URL to equal your NEXT_PUBLIC_WEBAPP_URL
# NEXTAUTH_URL='http://localhost:3000'
NEXTAUTH_URL=
NEXTAUTH_URL='http://localhost:3000'
# @see: https://next-auth.js.org/configuration/options#nextauth_secret
# You can use: `openssl rand -base64 32` to generate one
NEXTAUTH_SECRET=
# Used for cross-domain cookie authentication
NEXTAUTH_COOKIE_DOMAIN=.example.com
NEXTAUTH_COOKIE_DOMAIN=
# Set this to '1' if you don't want Cal to collect anonymous usage
CALCOM_TELEMETRY_DISABLED=
@@ -97,6 +94,8 @@ NEXT_PUBLIC_IS_E2E=
# Used for internal billing system
NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE=
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE=
NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=
NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRO_PLAN_PRODUCT_ID=
@@ -132,3 +131,9 @@ EMAIL_SERVER_PASSWORD='<office365_password>'
# Set the following value to true if you wish to enable Team Impersonation
NEXT_PUBLIC_TEAM_IMPERSONATION=false
# Close.com internal CRM
CLOSECOM_API_KEY=
# Sendgrid internal email sender
SENDGRID_API_KEY=
+1
View File
@@ -15,6 +15,7 @@ Fixes # (issue)
<!-- Please delete options that are not relevant. -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Chore (refactoring code, technical debt, workflow improvements)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
+16
View File
@@ -0,0 +1,16 @@
name: Add PRs to project
on:
pull_request:
types:
- opened
jobs:
add-PR-to-project:
name: Add PR to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.1.0
with:
project-url: https://github.com/orgs/calcom/projects/1
github-token: ${{ secrets.GH_ACCESS_TOKEN }}
@@ -12,6 +12,9 @@ on:
- apps/storybook/**
- packages/ui/**
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
# List of jobs
jobs:
+3
View File
@@ -5,6 +5,9 @@ on:
- main
paths:
- "**.tsx?"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
check-types:
runs-on: ubuntu-latest
+14 -12
View File
@@ -4,22 +4,24 @@ on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v2
- name: crowdin action
uses: crowdin/github-action@1.4.9
with:
upload_translations: true
download_translations: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: crowdin action
uses: crowdin/github-action@1.4.9
with:
upload_translations: true
download_translations: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+8 -5
View File
@@ -1,7 +1,7 @@
name: E2E App-Store Apps
on:
push:
branches: [ feature/event-routing ]
branches: [fixes/e2e-consolidation] # TODO: Remove this after merged in main
pull_request_target: # So we can test on forks
branches:
- main
@@ -12,6 +12,9 @@ on:
- apps/swagger/**
- apps/website/**
- apps/web/public/**
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 20
@@ -86,14 +89,14 @@ jobs:
restore-keys: cache-playwright-
- run: yarn --frozen-lockfile
- name: Install playwright deps
# if: steps.playwright-cache.outputs.cache-hit != 'true'
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn playwright install --with-deps
- name: Run Tests
run: yarn app-e2e-quick
run: yarn test-e2e:app-store
- name: Upload Test Results
if: ${{ always() }}
uses: actions/upload-artifact@v2
with:
name: test-results-core
path: packages/app-store/**/playwright/results
name: test-results
path: test-results
+6 -1
View File
@@ -7,6 +7,9 @@ on:
paths:
- apps/web/**
- packages/embeds/**
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
e2e-embed:
timeout-minutes: 20
@@ -25,6 +28,8 @@ jobs:
NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE: ${{ secrets.NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE }}
NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN: 1
STRIPE_PRIVATE_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }}
STRIPE_CLIENT_ID: ${{ secrets.CI_STRIPE_CLIENT_ID }}
STRIPE_WEBHOOK_SECRET: ${{ secrets.CI_STRIPE_WEBHOOK_SECRET }}
@@ -79,7 +84,7 @@ jobs:
restore-keys: cache-playwright-
- run: yarn --frozen-lockfile
- name: Install playwright deps
# if: steps.playwright-cache.outputs.cache-hit != 'true'
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn playwright install --with-deps
- name: Run Tests
run: yarn turbo run embed-tests-update-snapshots:ci --scope=@calcom/embed-react --concurrency=1
+7
View File
@@ -1,11 +1,16 @@
name: E2E test
on:
push:
branches: [fixes/e2e-consolidation] # TODO: Remove this after merged in main
pull_request_target: # So we can test on forks
branches:
- main
paths:
- apps/web/**
- packages/**
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
e2e:
timeout-minutes: 20
@@ -24,6 +29,8 @@ jobs:
NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE }}
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE: ${{ secrets.NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE }}
NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN: 1
STRIPE_PRIVATE_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }}
STRIPE_CLIENT_ID: ${{ secrets.CI_STRIPE_CLIENT_ID }}
STRIPE_WEBHOOK_SECRET: ${{ secrets.CI_STRIPE_WEBHOOK_SECRET }}
+3 -1
View File
@@ -1,7 +1,9 @@
name: "Pull Request Labeler"
on:
- pull_request_target
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
labeler:
permissions:
+3
View File
@@ -6,6 +6,9 @@ on:
paths:
- "**.tsx?"
- "**.jsx?"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
+9
View File
@@ -1,8 +1,13 @@
name: "Meta Workflow: Require Conditional Status Checks"
on:
push:
branches: [fixes/e2e-consolidation] # TODO: Remove this after merged in main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
required-checks:
runs-on: ubuntu-latest
@@ -34,3 +39,7 @@ jobs:
paths:
- /apps/web/**
- /packages/embeds/**
- job: test
paths:
- /apps/web/**
- /packages/**
+31
View File
@@ -0,0 +1,31 @@
name: Unit tests
on:
push:
branches: [fixes/e2e-consolidation] # TODO: Remove this after merged in main
pull_request_target: # So we can test on forks
branches:
- main
paths:
- apps/web/**
- packages/**
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 20
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }} # So we can test on forks
fetch-depth: 2
- run: echo 'NODE_OPTIONS="--max_old_space_size=4096"' >> $GITHUB_ENV
- name: Use Node 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: "yarn"
- run: yarn --frozen-lockfile
- run: yarn test
+11 -10
View File
@@ -58,15 +58,12 @@ Calendly and other scheduling tools are awesome. It made our lives massively eas
That's where Cal.com comes in. Self-hosted or hosted by us. White-label by design. API-driven and ready to be deployed on your own domain. Full control of your events and data.
## Product of the Month: April
## Product of the Month: April 2021
#### Support us on [Product Hunt](https://www.producthunt.com/posts/calendso?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-calendso)
<a href="https://www.producthunt.com/posts/calendso?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-calendso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=291910&theme=light&period=monthly" alt="Cal.com - The open source Calendly alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a> <a href="https://www.producthunt.com/posts/calendso?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-calendso" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=291910&theme=light" alt="Cal.com - The open source Calendly alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a> <a href="https://www.producthunt.com/stories/how-this-open-source-calendly-alternative-rocketed-to-product-of-the-day" target="_blank"><img src="https://cal.com/maker-grant.svg" alt="Cal.com - The open source Calendly alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
### Built With
- [Next.js](https://nextjs.org/)
@@ -118,7 +115,10 @@ Here is what you need to be able to run Cal.
yarn
```
1. Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the .env file.
1. Set up your .env file
- Duplicate `.env.example` to `.env`
- Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the .env file.
- Use `openssl rand -base64 24` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the .env file.
#### Quick start with `yarn dx`
@@ -207,7 +207,7 @@ Be sure to set the environment variable `NEXTAUTH_URL` to the correct value. If
yarn test-e2e
# To open last HTML report run:
yarn workspace @calcom/web playwright-report
yarn playwright show-report test-results/reports/playwright-html-report
```
### Upgrading from earlier versions
@@ -266,13 +266,13 @@ yarn workspace @calcom/web playwright-report
### Docker
The Docker configuration for Cal is an effort powered by people within the community.
The Docker configuration for Cal is an effort powered by people within the community.
If you want to contribute to the Docker repository, [reply here](https://github.com/calcom/docker/discussions/32).
The Docker configuration can be found [in our docker repository](https://github.com/calcom/docker).
Issues with Docker? Find your answer or open a new discussion [here](https://github.com/calcom/docker/discussions) to ask the community.
Issues with Docker? Find your answer or open a new discussion [here](https://github.com/calcom/docker/discussions) to ask the community.
Cal.com, Inc. does not provide official support for Docker, but we will accept fixes and documentation. Use at your own risk.
@@ -284,7 +284,7 @@ Cal.com, Inc. does not provide official support for Docker, but we will accept f
### Railway
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template?template=https%3A%2F%2Fgithub.com%2Fcalendso%2Fcalendso&plugins=postgresql&envs=GOOGLE_API_CREDENTIALS%2CBASE_URL%2CNEXTAUTH_URL%2CPORT&BASE_URLDefault=http%3A%2F%2Flocalhost%3A3000&NEXTAUTH_URLDefault=http%3A%2F%2Flocalhost%3A3000&PORTDefault=3000)
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/cal)
You can deploy Cal on [Railway](https://railway.app/) using the button above. The team at Railway also have a [detailed blog post](https://blog.railway.app/p/calendso) on deploying Cal on their platform.
@@ -328,7 +328,7 @@ We have a list of [help wanted](https://github.com/orgs/calcom/projects/1/views/
10. The key will be created and you will be redirected back to the Credentials page. Select the newly generated client ID under OAuth 2.0 Client IDs.
11. Select Download JSON. Copy the contents of this file and paste the entire JSON string in the .env file as the value for GOOGLE_API_CREDENTIALS key.
#### *Adding google calendar to Cal.com App Store*
#### _Adding google calendar to Cal.com App Store_
After adding Google credentials, you can now Google Calendar App to the app store.
You can repopulate the App store by running
@@ -344,6 +344,7 @@ following
1. Add extra redirect URL `<Cal.com URL>/api/auth/callback/google`
1. Under 'OAuth concent screen', click "PUBLISH APP"
### Obtaining Microsoft Graph Client ID and Secret
1. Open [Azure App Registration](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps) and select New registration
+34
View File
@@ -0,0 +1,34 @@
/**
* This is a Playwright script Checkly generated for you based on your Vercel project.
* To learn more about Browser checks and Playwright visit: https://www.checklyhq.com/docs/browser-checks
*/
// Create a Chromium browser
const { chromium } = require("playwright");
// Checkly supports top level await, but we wrap your code in an async function so you can run it locally too.
async function run() {
const browser = await chromium.launch();
const page = await browser.newPage();
// If available, we set the target URL to a preview deployment URL provided by the ENVIRONMENT_URL created by Vercel.
// Otherwise, we use the Production URL.
const targetUrl = process.env.ENVIRONMENT_URL || "https://app.cal.com";
// We visit the page. This waits for the "load" event by default.
const response = await page.goto(targetUrl);
// If the page doesn't return a successful response code, we fail the check
if (response.status() > 399) {
throw new Error(`Failed with response code ${response.status()}`);
}
// We snap a screenshot.
await page.screenshot({ path: "screenshot.jpg" });
// We close the page and browser. This is needed for collecting accurate web vitals.
await page.close();
await browser.close();
}
run();
+4 -4
View File
@@ -17,14 +17,14 @@
"license": "MIT",
"dependencies": {
"iframe-resizer-react": "^1.1.0",
"next": "^12.2.0",
"next": "^12.2.5",
"nextra": "^1.1.0",
"nextra-theme-docs": "^1.2.2",
"react": "^18.1.0",
"react-dom": "^18.1.0"
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@calcom/config": "*",
"eslint": "^8.15.0"
"eslint": "^8.22.0"
}
}
+1
View File
@@ -11,6 +11,7 @@
# next.js
/.next/
/out/
next-env.d.ts
# production
/build
+4
View File
@@ -20,6 +20,10 @@ module.exports = {
* @see https://github.com/storybookjs/storybook/issues/12844#issuecomment-867544160
*/
config.resolve.roots = [path.resolve(__dirname, "../public"), "node_modules"];
config.resolve.alias = {
...config.resolve.alias,
"@/interfaces": path.resolve(__dirname, "../interfaces"),
};
/**
* Why webpack5... Just why?
+10
View File
@@ -22,3 +22,13 @@ export const parameters = {
Provider: RouterContext.Provider,
},
};
window.getEmbedNamespace = () => {
const url = new URL(document.URL);
const namespace = url.searchParams.get("embed");
return namespace;
};
window.getEmbedTheme = () => {
return "auto";
};
-5
View File
@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
+24 -22
View File
@@ -23,40 +23,42 @@
"@radix-ui/react-radio-group": "^0.1.1",
"@radix-ui/react-slider": "^0.1.1",
"@radix-ui/react-switch": "^0.1.1",
"@radix-ui/react-tooltip": "^0.1.0",
"next": "^12.2.0",
"@radix-ui/react-tooltip": "^1.0.0",
"next": "^12.2.5",
"next-transpile-modules": "^9.0.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-feather": "^2.0.9",
"react-hot-toast": "^2.2.0"
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-feather": "^2.0.10",
"react-hot-toast": "^2.3.0"
},
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/core": "^7.18.10",
"@calcom/config": "*",
"@storybook/addon-a11y": "^6.5.9",
"@storybook/addon-actions": "^6.5.9",
"@storybook/addon-essentials": "^6.5.9",
"@storybook/addon-interactions": "^6.5.9",
"@storybook/addon-links": "^6.5.9",
"@storybook/addon-a11y": "^6.5.10",
"@storybook/addon-actions": "^6.5.10",
"@storybook/addon-essentials": "^6.5.10",
"@storybook/addon-interactions": "^6.5.10",
"@storybook/addon-links": "^6.5.10",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.5.9",
"@storybook/manager-webpack5": "^6.5.9",
"@storybook/react": "^6.5.9",
"@storybook/builder-vite": "^0.2.2",
"@storybook/builder-webpack5": "^6.5.10",
"@storybook/manager-webpack5": "^6.5.10",
"@storybook/react": "^6.5.10",
"@tailwindcss/line-clamp": "^0.4.0",
"@types/node": "16.9.1",
"@types/react": "18.0.9",
"@types/react": "^18.0.17",
"@types/react-dom": "18.0.4",
"autoprefixer": "^10.4.7",
"autoprefixer": "^10.4.8",
"babel-loader": "^8.2.5",
"chromatic": "^6.6.4",
"eslint": "^8.15.0",
"postcss": "^8.4.13",
"chromatic": "^6.7.4",
"eslint": "^8.22.0",
"postcss": "^8.4.16",
"postcss-loader": "^7.0.0",
"storybook-addon-designs": "^6.3.1",
"storybook-addon-next": "^1.6.7",
"tailwindcss": "^3.1.3",
"tailwindcss": "^3.1.8",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.4"
"typescript": "^4.7.4"
},
"readme": "ERROR: No README data found!",
"_id": "@calcom/storybook@0.1.0"
+1 -1
View File
@@ -1,6 +1,6 @@
import { ComponentMeta } from "@storybook/react";
import Avatar from "@calcom/ui/v2/Avatar";
import Avatar from "@calcom/ui/v2/core/Avatar";
export default {
title: "Avatar",
@@ -1,7 +1,7 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { ComponentMeta } from "@storybook/react";
import Avatar from "@calcom/ui/v2/Avatar";
import AvatarGroup from "@calcom/ui/v2/AvatarGroup";
import AvatarGroup from "@calcom/ui/v2/core/AvatarGroup";
export default {
title: "Avatar/Group",
@@ -53,8 +53,8 @@ const IMAGES = [
export const Default = () => {
return (
<>
<TooltipProvider>
<AvatarGroup size="lg" items={IMAGES} />
</>
</TooltipProvider>
);
};
+1 -1
View File
@@ -1,7 +1,7 @@
import { ComponentMeta } from "@storybook/react";
import { Bell } from "react-feather";
import { Badge } from "@calcom/ui/v2";
import Badge from "@calcom/ui/v2/core/Badge";
export default {
title: "Badge",
+1 -1
View File
@@ -1,7 +1,7 @@
import { ComponentStory, ComponentMeta } from "@storybook/react";
import { Info } from "react-feather";
import { Banner } from "@calcom/ui/v2";
import Banner from "@calcom/ui/v2/core/banner";
export default {
title: "Banner",
@@ -1,6 +1,6 @@
import { ComponentMeta } from "@storybook/react";
import { Breadcrumb, BreadcrumbItem } from "@calcom/ui/v2";
import Breadcrumb, { BreadcrumbItem } from "@calcom/ui/v2/core/Breadcrumb";
export default {
title: "Breadcrumbs",
+48 -45
View File
@@ -1,11 +1,12 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { Trash2 } from "react-feather";
import { Button as ButtonComponent } from "@calcom/ui/v2";
import Button from "@calcom/ui/v2/core/Button";
export default {
title: "Button",
component: ButtonComponent,
component: Button,
argTypes: {
color: {
options: ["primary", "secondary", "minimal", "destructive"],
@@ -24,67 +25,69 @@ export default {
control: { type: "radio" },
},
},
} as ComponentMeta<typeof ButtonComponent>;
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof ButtonComponent> = (args) => <ButtonComponent {...args} />;
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const All = () => (
<div>
<h1>Primary</h1>
<div className="flex space-x-2">
<ButtonComponent aria-label="Button Text">Button Text</ButtonComponent>
<ButtonComponent disabled aria-label="Button Text">
Button Text
</ButtonComponent>
</div>
<h1>Secondary</h1>
<div className="flex space-x-2">
<ButtonComponent color="secondary" aria-label="Button Text">
Button Text
</ButtonComponent>
<ButtonComponent disabled color="secondary" aria-label="Button Text">
Button Text
</ButtonComponent>
<ButtonComponent size="icon" color="secondary" StartIcon={Trash2} aria-label="Button Text" />
</div>
<h1>Minimal</h1>
<div className="flex">
<ButtonComponent color="minimal" aria-label="Button Text">
Button Text
</ButtonComponent>
<ButtonComponent disabled color="minimal" aria-label="Button Text">
Button Text
</ButtonComponent>
<ButtonComponent size="icon" color="minimal" StartIcon={Trash2} aria-label="Button Text" />
</div>
<h1>Destructive</h1>
<ButtonComponent size="icon" color="destructive" StartIcon={Trash2} aria-label="Button Text" />
<h1>Tooltip</h1>
<ButtonComponent
tooltip="Deletes EventTypes"
size="icon"
color="destructive"
StartIcon={Trash2}
aria-label="Button Text"
/>
<TooltipProvider>
<h1>Primary</h1>
<div className="flex space-x-2">
<Button aria-label="Button Text">Button Text</Button>
<Button disabled aria-label="Button Text">
Button Text
</Button>
</div>
<h1>Secondary</h1>
<div className="flex space-x-2">
<Button color="secondary" aria-label="Button Text">
Button Text
</Button>
<Button disabled color="secondary" aria-label="Button Text">
Button Text
</Button>
<Button size="icon" color="secondary" StartIcon={Trash2} aria-label="Button Text" />
</div>
<h1>Minimal</h1>
<div className="flex">
<Button color="minimal" aria-label="Button Text">
Button Text
</Button>
<Button disabled color="minimal" aria-label="Button Text">
Button Text
</Button>
<Button size="icon" color="minimal" StartIcon={Trash2} aria-label="Button Text" />
</div>
<h1>Destructive</h1>
<Button size="icon" color="destructive" StartIcon={Trash2} aria-label="Button Text" />
<h1>Tooltip</h1>
<Button
tooltip="Deletes EventTypes"
size="icon"
color="destructive"
StartIcon={Trash2}
aria-label="Button Text"
/>
</TooltipProvider>
</div>
);
export const Button = Template.bind({});
Button.args = {
export const Default = Template.bind({});
Default.args = {
color: "primary",
children: "Button Text",
};
export const Disabled = Template.bind({});
Disabled.args = {
...Button.args,
...Default.args,
disabled: true,
};
export const Loading = Template.bind({});
Loading.args = {
...Button.args,
...Default.args,
loading: true,
};
export const Icon = Template.bind({});
+16 -6
View File
@@ -1,11 +1,20 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { ComponentMeta } from "@storybook/react";
import { ArrowLeft, ArrowRight, Clipboard, Navigation2, Trash2 } from "react-feather";
import { Button, ButtonGroup } from "@calcom/ui/v2";
import Button from "@calcom/ui/v2/core/Button";
import ButtonGroup from "@calcom/ui/v2/core/ButtonGroup";
export default {
title: "Button Group",
component: ButtonGroup,
decorators: [
(Story) => (
<TooltipProvider>
<Story />
</TooltipProvider>
),
],
} as ComponentMeta<typeof ButtonGroup>;
export const Default = () => (
@@ -19,13 +28,14 @@ export const Default = () => (
export const Combined = () => (
<div className="flex flex-col space-y-2">
<ButtonGroup combined>
<Button StartIcon={Trash2} size="icon" color="secondary" combined />
<Button StartIcon={Navigation2} size="icon" color="secondary" combined />
<Button StartIcon={Clipboard} size="icon" color="secondary" combined />
<Button StartIcon={Trash2} size="icon" color="secondary" />
<Button StartIcon={Navigation2} size="icon" color="secondary" />
<Button StartIcon={Clipboard} size="icon" color="secondary" />
</ButtonGroup>
<ButtonGroup combined>
<Button StartIcon={ArrowLeft} size="icon" color="secondary" combined />
<Button StartIcon={ArrowRight} size="icon" color="secondary" combined />
<Button StartIcon={ArrowLeft} size="icon" color="secondary" />
<Button StartIcon={ArrowRight} size="icon" color="secondary" />
<Button StartIcon={ArrowRight} href="/" size="icon" color="secondary" />
</ButtonGroup>
</div>
);
+27 -1
View File
@@ -1,6 +1,7 @@
import { ComponentMeta } from "@storybook/react";
import { useState } from "react";
import { BaseCardProps, Card } from "@calcom/ui/v2/Card";
import Card, { BaseCardProps } from "@calcom/ui/v2/core/Card";
export default {
title: "Cards",
@@ -51,3 +52,28 @@ export const AppStore = () => {
</div>
);
};
const sidebarCardProps: BaseCardProps = {
variant: "SidebarCard",
thumbnailUrl: "https://img.youtube.com/vi/60HJt8DOVNo/0.jpg",
mediaLink: "https://www.youtube.com/watch?v=60HJt8DOVNo",
title: "Dynamic boooking links",
description: "Booking link that allows people to quickly schedule meetings.",
learnMore: {
href: "https://cal.com/blog/cal-v-1-9",
text: "Learn more",
},
};
export const SidebarCard = () => {
const [visible, setVisible] = useState(true); // save state in localStorage, cookie or db
return (
<header className="w-full max-w-[225px] bg-gray-100 p-3">
{visible && (
<div>
<Card {...sidebarCardProps} actionButton={{ onClick: () => setVisible(false), child: "Dismiss" }} />
</div>
)}
</header>
);
};
+1 -1
View File
@@ -1,6 +1,6 @@
import { ComponentMeta } from "@storybook/react";
import { Checkbox } from "@calcom/ui/v2";
import Checkbox from "@calcom/ui/v2/core/form/Checkbox";
export default {
title: "Checkbox",
+1 -1
View File
@@ -1,6 +1,6 @@
import { useState } from "react";
import ColorPicker from "@calcom/ui/v2/colorpicker";
import ColorPicker from "@calcom/ui/v2/core/colorpicker";
// eslint-disable-next-line import/no-anonymous-default-export
export default {
@@ -1,6 +1,6 @@
import { useState } from "react";
import DatePicker from "@calcom/ui/v2/booker/DatePicker";
import DatePicker from "@calcom/ui/v2/modules/booker/DatePicker";
export default {
title: "Datepicker",
@@ -8,7 +8,7 @@ export default {
};
export const Default = () => {
const [selected, setSelected] = useState<Date | undefined>(undefined);
const [selected, setSelected] = useState<Date>(new Date());
return (
<div style={{ width: "455px" }}>
<DatePicker selected={selected} onChange={setSelected} locale="en" />
@@ -0,0 +1,45 @@
import { ComponentMeta, ComponentStory } from "@storybook/react";
import "@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css";
import { useState } from "react";
import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker";
import "@calcom/ui/v2/core/form/date-range-picker/styles.css";
function getISOLocalDate(date) {
const year = padStart(date.getFullYear(), 4);
const month = padStart(date.getMonth() + 1);
const day = padStart(date.getDate());
return [`${year}-${month}-${day}`];
}
function padStart(num, val = 2) {
const numStr = `${num}`;
if (numStr.length >= val) {
return num;
}
return `0000${numStr}`.slice(-val);
}
export default {
title: "Date Range Picker",
component: DateRangePicker,
} as ComponentMeta<typeof DateRangePicker>;
export const Default: ComponentStory<typeof DateRangePicker> = () => {
const [startDate, setStartDate] = useState<Date>(new Date());
const [endDate, setEndDate] = useState<Date>(new Date());
return (
<div>
<DateRangePicker
startDate={getISOLocalDate(startDate) as unknown as Date}
endDate={getISOLocalDate(endDate) as unknown as Date}
onDatesChange={({ startDate, endDate }) => {
setStartDate(startDate);
setEndDate(endDate);
}}
/>
</div>
);
};
@@ -1,11 +1,11 @@
import { ComponentMeta } from "@storybook/react";
import { Bell } from "react-feather";
import { EmptyScreen as EmptyScreenPattern } from "@calcom/ui/v2";
import EmptyScreen from "@calcom/ui/v2/core/EmptyScreen";
export default {
title: "pattern/Empty Screen",
component: EmptyScreenPattern,
component: EmptyScreen,
decorators: [
(Story) => (
<div className="flex items-center justify-center">
@@ -13,13 +13,13 @@ export default {
</div>
),
],
} as ComponentMeta<typeof EmptyScreenPattern>;
} as ComponentMeta<typeof EmptyScreen>;
export const EmptyScreenS = () => (
<EmptyScreenPattern
export const Default = () => (
<EmptyScreen
Icon={Bell}
headline="Empty State Header"
description="Ullamco dolor nulla sint nulla occaecat aliquip id elit fugiat et excepteur magna. Nisi tempor anim do tempor irure fugiat ad occaecat. Mollit ea eiusmod pariatur sunt deserunt eu eiusmod. Sit reprehenderit cupidatat consequat commodo in aliqua ea et. Et quis sit enim proident dolor mollit consectetur tempor dolore reprehenderit consequat adipisicing reprehenderit officia. Sint eu sunt fugiat laborum Lorem irure aute nulla et. Do non in enim ipsum ea."
description="Ullamco dolor nulla sint nulla occaecat aliquip id elit fugiat et excepteur magna. Nisi tempor anim do tempor irure fugiat ad occaecat. Mollit ea eiusmod pariatur sunt deserunt eu eiusmod. Sit reprehenderit "
buttonText="Veniam ut ipsum"
buttonOnClick={() => console.log("Button Clicked")}
/>
+1 -1
View File
@@ -1,7 +1,7 @@
import { ComponentMeta } from "@storybook/react";
import { useState } from "react";
import { FormStep } from "@calcom/ui/v2";
import FormStep from "@calcom/ui/v2/core/form/FormStep";
export default {
title: "Form Step",
@@ -1,8 +1,8 @@
// Disabling until we figure out what is happening with the RouterMock.
import { ComponentMeta } from "@storybook/react";
import { HorizontalTabs } from "@calcom/ui/v2/navigation/tabs";
import { HorizontalTabItemProps } from "@calcom/ui/v2/navigation/tabs/HorizontalTabItem";
import { HorizontalTabItemProps } from "@calcom/ui/v2/core/navigation/tabs/HorizontalTabItem";
import HorizontalTabs from "@calcom/ui/v2/core/navigation/tabs/HorizontalTabs";
export default {
title: "Horizontal Tabs",
@@ -14,10 +14,19 @@ const HorizontalTabsPropsDefault: HorizontalTabItemProps[] = [
name: "Tab One",
href: "/tab-one",
},
{
name: "Tab Two",
href: "/tab-two",
},
{
name: "Tab Disabled",
href: "/tab-disabled",
disabled: true,
},
];
export const Default = () => (
<div className="w-full p-4" style={{ backgroundColor: "#F9FAFB" }}>
<div className="w-full p-4">
<HorizontalTabs tabs={HorizontalTabsPropsDefault} />
</div>
);
@@ -25,6 +34,6 @@ export const Default = () => (
Default.parameters = {
nextRouter: {
path: "/[page]",
asPath: "/profile",
asPath: "/tab-one",
},
};
+2 -2
View File
@@ -1,8 +1,8 @@
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { Copy } from "react-feather";
import DatePicker from "@calcom/ui/v2/form/DatePicker";
import { TextAreaField, TextField } from "@calcom/ui/v2/form/fields";
import { TextAreaField, TextField } from "@calcom/ui/v2/core/form/fields";
import DatePicker from "@calcom/ui/v2/modules/booker/DatePicker";
export default {
title: "Inputs",
+1 -3
View File
@@ -1,9 +1,7 @@
import { useState } from "react";
import { Info } from "react-feather";
import { Button } from "@calcom/ui/v2";
import { Dialog, DialogContent, DialogTrigger } from "@calcom/ui/v2/Dialog";
import { TextField } from "@calcom/ui/v2/form/fields";
import { Button, Dialog, DialogContent, DialogTrigger, TextField } from "@calcom/ui/v2";
export default {
title: "pattern/Modal",
@@ -1,8 +1,7 @@
import { ComponentMeta } from "@storybook/react";
import { Toaster } from "react-hot-toast";
import { Button } from "@calcom/ui/v2";
import showToast from "@calcom/ui/v2/notfications";
import { Button, showToast } from "@calcom/ui/v2";
export default {
title: "Notifcations-Toasts",
@@ -1,8 +1,8 @@
import { ComponentMeta } from "@storybook/react";
import { Search } from "react-feather";
import { Button, PageHeader } from "@calcom/ui/v2";
import { TextField } from "@calcom/ui/v2/form";
import { Button, TextField } from "@calcom/ui/v2";
import PageHeader from "@calcom/ui/v2/core/PageHeader";
export default {
title: "pattern/Page Header",
+2 -2
View File
@@ -1,5 +1,5 @@
import * as Radio from "@calcom/ui/v2/form/radio-area/Radio";
import { RadioField } from "@calcom/ui/v2/form/radio-area/Radio";
import * as Radio from "@calcom/ui/v2/core/form/radio-area/Radio";
import { RadioField } from "@calcom/ui/v2/core/form/radio-area/Radio";
export default {
title: "Radio",
+24 -1
View File
@@ -1,10 +1,33 @@
import { ComponentMeta } from "@storybook/react";
import { Select } from "@calcom/ui/v2";
import MultiDropdownSelect from "@calcom/ui/v2/modules/event-types/MultiDropdownSelect";
export default {
title: "Form/Select",
component: Select,
} as ComponentMeta<typeof Select>;
export const Single = () => <Select items={[{ value: "Test Test" }]} />;
const singleOptions = [
{
label: "Select",
value: 0,
},
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
label: minutes + " " + "minutes",
value: minutes,
})),
];
const multiOptions = [
{
label: "Select",
value: 0,
},
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
label: minutes + " " + "minutes",
value: minutes,
})),
];
export const Single = () => <Select options={singleOptions} />;
export const Multi = () => <MultiDropdownSelect options={multiOptions} />;
+42 -42
View File
@@ -16,52 +16,52 @@ const TabItemProps = {
info: "60 mins, Zoom",
};
// export const Default = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem {...TabItemProps}></VerticalTabItem>
// </div>
// );
// export const Active = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem {...TabItemProps}></VerticalTabItem>
// </div>
// );
export const Default = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem {...TabItemProps} />
</div>
);
export const Active = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem {...TabItemProps} />
</div>
);
// Mocking next router to show active state
// Active.parameters = {
// nextRouter: {
// path: "/settings/[tab]",
// asPath: "/settings/event",
// },
// };
Active.parameters = {
nextRouter: {
path: "/settings/[tab]",
asPath: "/settings/event",
},
};
// export const Disabled = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem {...TabItemProps} disabled></VerticalTabItem>
// </div>
// );
export const Disabled = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem {...TabItemProps} disabled />
</div>
);
// export const NoIconNoInfo = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem name="Event Setup" href="/settings/event"></VerticalTabItem>
// </div>
// );
export const NoIconNoInfo = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem name="Event Setup" href="/settings/event" />
</div>
);
// export const IconNoInfo = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem name="Event Setup" href="/settings/event" icon={Link}></VerticalTabItem>
// </div>
// );
export const IconNoInfo = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem name="Event Setup" href="/settings/event" icon={Link} />
</div>
);
// export const IconNoInfoActive = () => (
// <div className="h-20 w-full bg-gray-100 p-4">
// <VerticalTabItem name="Event Setup" href="/settings/events" icon={Link}></VerticalTabItem>
// </div>
// );
export const IconNoInfoActive = () => (
<div className="h-20 w-full bg-gray-100 p-4">
<VerticalTabItem name="Event Setup" href="/settings/events" icon={Link} />
</div>
);
// IconNoInfoActive.paramaters = {
// nextRouter: {
// path: "/settings/[tab]",
// asPath: "/settings/events",
// },
// };
IconNoInfoActive.paramaters = {
nextRouter: {
path: "/settings/[tab]",
asPath: "/settings/events",
},
};
@@ -2,7 +2,7 @@
import { ComponentMeta } from "@storybook/react";
import { Calendar, Clock, Grid, Link, RefreshCw, User, Users } from "react-feather";
import { VerticalTabs } from "@calcom/ui/v2/navigation/tabs";
import VerticalTabs from "@calcom/ui/v2/core/navigation/tabs/VerticalTabs";
export default {
title: "Vertical Tabs",
+3
View File
@@ -2,6 +2,9 @@
@tailwind components;
@tailwind utilities;
@import "../../../packages/ui/v2/core/form/date-range-picker/styles.css";
@import "../../../node_modules/@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css";
:root {
--brand-color: #292929;
--brand-text-color: #ffffff;
+6 -6
View File
@@ -12,18 +12,18 @@
"start": "PORT=4200 next start"
},
"dependencies": {
"highlight.js": "^11.5.1",
"highlight.js": "^11.6.0",
"isarray": "2.0.5",
"next": "12.2.0",
"next": "^12.2.5",
"openapi-snippet": "^0.13.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"swagger-ui-react": "4.11.1"
},
"devDependencies": {
"@types/node": "16.9.1",
"@types/react": "18.0.9",
"@types/react": "^18.0.17",
"@types/react-dom": "18.0.4",
"typescript": "4.6.4"
"typescript": "^4.7.4"
}
}
+4
View File
@@ -21,6 +21,7 @@ playwright/reports/*
# next.js
/.next/
/out/
next-env.d.ts
# production
/build
@@ -64,3 +65,6 @@ tsconfig.tsbuildinfo
# Autogenerated embed content
public/embed
# Copied app-store images
public/app-store
-173
View File
@@ -277,179 +277,6 @@ paths:
type: string
integration:
type: string
/api/availability/day:
patch:
description: Updates the start and end times for a user's availability.
summary: Updates the user's start and end times
tags:
- Availability
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
message:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
startMins:
type: string
endMins:
type: string
bufferMins:
type: string
description: ""
/api/availability/eventtype:
post:
description: Adds a new event type for the user.
summary: Adds a new event type
tags:
- Availability
requestBody:
content:
application/json:
schema:
type: object
properties:
title:
type: string
slug:
type: string
description:
type: string
length:
type: string
hidden:
type: boolean
requiresConfirmation:
type: boolean
locations:
type: array
items: {}
eventName:
type: string
customInputs:
type: array
items: {}
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
eventType:
type: object
properties:
title:
type: string
slug:
type: string
description:
type: string
length:
type: string
hidden:
type: boolean
requiresConfirmation:
type: boolean
locations:
type: array
items: {}
eventName:
type: string
customInputs:
type: array
items: {}
"500":
description: Internal Server Error
patch:
description: Updates an event type for the user.
summary: Updates an event type
tags:
- Availability
requestBody:
content:
application/json:
schema:
type: object
properties:
title:
type: string
slug:
type: string
description:
type: string
length:
type: string
hidden:
type: boolean
requiresConfirmation:
type: boolean
locations:
type: array
items: {}
eventName:
type: string
customInputs:
type: array
items: {}
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
eventType:
type: object
properties:
title:
type: string
slug:
type: string
description:
type: string
length:
type: string
hidden:
type: boolean
requiresConfirmation:
type: boolean
locations:
type: array
items: {}
eventName:
type: string
customInputs:
type: array
items: {}
"500":
description: Internal Server Error
delete:
description: Deletes an event type for the user.
summary: Deletes an event type
tags:
- Availability
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties: {}
"500":
description: Internal Server Error
"/api/book/event":
post:
description: Creates a booking in the user's calendar.
+2 -2
View File
@@ -9,9 +9,9 @@ import showToast from "@calcom/lib/notification";
import { trpc } from "@calcom/trpc/react";
import { App as AppType } from "@calcom/types/App";
import { Button, SkeletonButton } from "@calcom/ui";
import Badge from "@calcom/ui/Badge";
import { Icon } from "@calcom/ui/Icon";
import Shell from "@calcom/ui/Shell";
import Badge from "@calcom/ui/v2/core/Badge";
const Component = ({
name,
@@ -80,7 +80,7 @@ const Component = ({
return (
<div className="-mx-4 md:-mx-8">
<div className="bg-gray-50 px-8">
<div className="px-8">
<Link href="/apps">
<a className="mt-2 inline-flex px-1 py-2 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-800">
<Icon.FiChevronLeft className="h-5 w-5" /> {t("browse_apps")}
@@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react";
import Select from "react-select";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { DestinationCalendar } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
interface Props {
@@ -11,6 +12,7 @@ interface Props {
hidePlaceholder?: boolean;
/** The external Id of the connected calendar */
value: string | undefined;
destinationCalendar?: DestinationCalendar | null;
}
const DestinationCalendarSelector = ({
@@ -18,6 +20,7 @@ const DestinationCalendarSelector = ({
isLoading,
value,
hidePlaceholder,
destinationCalendar,
}: Props): JSX.Element | null => {
const { t } = useLocale();
const query = trpc.useQuery(["viewer.connectedCalendars"]);
@@ -67,11 +70,26 @@ const DestinationCalendarSelector = ({
value: `${cal.integration}:${cal.externalId}`,
})),
})) ?? [];
const defaultCalendarSelectedString = destinationCalendar?.externalId
? `(${
destinationCalendar.externalId.length > 15
? destinationCalendar.externalId.substring(0, 15) + "..."
: destinationCalendar.externalId
})`
: "";
return (
<div className="relative" title={`${t("select_destination_calendar")}: ${selectedOption?.label || ""}`}>
<Select
name="primarySelectedCalendar"
placeholder={!hidePlaceholder ? `${t("select_destination_calendar")}:` : undefined}
placeholder={
!hidePlaceholder ? (
`${t("select_destination_calendar")}`
) : (
<span className="whitespace-nowrap">
{t("default_calendar_selected")} {defaultCalendarSelectedString}
</span>
)
}
options={options}
styles={{
placeholder: (styles) => ({ ...styles, ...content(hidePlaceholder) }),
@@ -89,10 +107,10 @@ const DestinationCalendarSelector = ({
control: (defaultStyles) => {
return {
...defaultStyles,
borderRadius: "2px",
borderRadius: "6px",
"@media only screen and (min-width: 640px)": {
...(defaultStyles["@media only screen and (min-width: 640px)"] as object),
maxWidth: "320px",
width: "100%",
},
};
},
@@ -118,6 +136,9 @@ const DestinationCalendarSelector = ({
}}
isLoading={isLoading}
value={selectedOption}
components={{
IndicatorSeparator: () => null,
}}
/>
</div>
);
+13 -6
View File
@@ -6,10 +6,10 @@ import { components, ControlProps } from "react-select";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import showToast from "@calcom/lib/notification";
import { Button, Switch } from "@calcom/ui";
import { Dialog, DialogClose, DialogContent } from "@calcom/ui/Dialog";
import { Icon } from "@calcom/ui/Icon";
import { InputLeading, Label, TextArea, TextField } from "@calcom/ui/form/fields";
import { Button, Switch } from "@calcom/ui/v2";
import { EMBED_LIB_URL, WEBAPP_URL } from "@lib/config/constants";
@@ -222,7 +222,11 @@ const getEmbedTypeSpecificString = ({
if (!frameworkCodes) {
throw new Error(`No code available for the framework:${embedFramework}`);
}
let uiInstructionStringArg = undefined;
let uiInstructionStringArg: {
apiName: string;
theme: PreviewState["theme"];
brandColor: string;
};
if (embedFramework === "react") {
uiInstructionStringArg = {
apiName: "cal",
@@ -545,7 +549,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "react", embedType, calLink, prev
type: "iframe",
Component: forwardRef<
HTMLIFrameElement | HTMLTextAreaElement | null,
{ calLink: string; embedType: EmbedType }
{ calLink: string; embedType: EmbedType; previewState: PreviewState }
>(function Preview({ calLink, embedType }, ref) {
if (ref instanceof Function || !ref) {
return null;
@@ -1124,7 +1128,7 @@ export const EmbedDialog = () => {
type EmbedButtonProps<T> = {
embedUrl: string;
children?: React.ReactNode;
className: string;
className?: string;
as?: T;
};
@@ -1136,7 +1140,7 @@ export const EmbedButton = <T extends React.ElementType>({
...props
}: EmbedButtonProps<T> & React.ComponentPropsWithoutRef<T>) => {
const router = useRouter();
className = classNames(className, "hidden lg:flex");
className = classNames(className, "hidden lg:inline-flex");
const openEmbedModal = () => {
const query = {
...router.query,
@@ -1160,7 +1164,10 @@ export const EmbedButton = <T extends React.ElementType>({
className={className}
data-test-embed-url={embedUrl}
data-testid="embed"
onClick={() => openEmbedModal()}>
type="button"
onClick={() => {
openEmbedModal();
}}>
{children}
</Component>
);
+49
View File
@@ -0,0 +1,49 @@
import { Dispatch, useState, useEffect } from "react";
import { JSONObject } from "superjson/dist/types";
import RainbowGate from "@calcom/app-store/rainbow/components/RainbowKit";
export type Gate = undefined | "rainbow"; // Add more like ` | "geolocation" | "payment"`
export type GateState = {
rainbowToken?: string;
};
type GateProps = {
children: React.ReactNode;
gates: Gate[];
metadata: JSONObject;
dispatch: Dispatch<Partial<GateState>>;
};
// To add a new Gate just add the gate logic to the switch statement
const Gates: React.FC<GateProps> = ({ children, gates, metadata, dispatch }) => {
const [rainbowToken, setRainbowToken] = useState<string>();
useEffect(() => {
dispatch({ rainbowToken });
}, [rainbowToken, dispatch]);
let gateWrappers = <>{children}</>;
// Recursively wraps the `gateWrappers` with new gates allowing for multiple gates
for (const gate of gates) {
switch (gate) {
case "rainbow":
if (metadata.blockchainId && metadata.smartContractAddress && !rainbowToken) {
gateWrappers = (
<RainbowGate
setToken={setRainbowToken}
chainId={metadata.blockchainId as number}
tokenAddress={metadata.smartContractAddress as string}>
{gateWrappers}
</RainbowGate>
);
}
}
}
return gateWrappers;
};
export default Gates;
+1
View File
@@ -63,6 +63,7 @@ function CropContainer({
);
}
/** @deprecated Use `packages/ui/v2/core/ImageUploader.tsx` */
export default function ImageUploader({
target,
id,
+3
View File
@@ -1 +1,4 @@
/**
* @deprecated Use custom Skeletons instead
**/
export { default } from "@calcom/ui/Loader";
+1 -10
View File
@@ -11,16 +11,7 @@ export default function AllApps({ apps }: { apps: App[] }) {
<h2 className="mb-2 text-lg font-semibold text-gray-900">{t("all_apps")}</h2>
<div className="grid-col-1 grid grid-cols-1 gap-3 md:grid-cols-3">
{apps.map((app) => (
<AppCard
key={app.name}
name={app.name}
slug={app.slug}
description={app.description}
logo={app.logo}
rating={app.rating}
reviews={app.reviews}
isProOnly={app.isProOnly}
/>
<AppCard key={app.name} app={app} />
))}
</div>
</div>
+8 -14
View File
@@ -1,31 +1,25 @@
import Link from "next/link";
import { trpc } from "@calcom/trpc/react";
import { App } from "@calcom/types/App";
import Badge from "@calcom/ui/Badge";
import Button from "@calcom/ui/Button";
interface AppCardProps {
logo: string;
name: string;
slug?: string;
category?: string;
description: string;
rating: number;
reviews?: number;
isProOnly?: boolean;
app: App;
}
export default function AppCard(props: AppCardProps) {
const { data: user } = trpc.useQuery(["viewer.me"]);
return (
<Link href={"/apps/" + props.slug}>
<Link href={"/apps/" + props.app.slug}>
<a
className="block h-full rounded-sm border border-gray-300 p-5 hover:bg-neutral-50"
data-testid={`app-store-app-card-${props.slug}`}>
data-testid={`app-store-app-card-${props.app.slug}`}>
<div className="flex">
{
// eslint-disable-next-line @next/next/no-img-element
<img src={props.logo} alt={props.name + " Logo"} className="mb-4 h-12 w-12 rounded-sm" />
<img src={props.app.logo} alt={props.app.name + " Logo"} className="mb-4 h-12 w-12 rounded-sm" />
}
<Button
color="secondary"
@@ -37,8 +31,8 @@ export default function AppCard(props: AppCardProps) {
</Button>
</div>
<div className="flex items-center">
<h3 className="font-medium">{props.name}</h3>
{props.isProOnly && user?.plan === "FREE" ? (
<h3 className="font-medium">{props.app.name}</h3>
{props.app.isProOnly && user?.plan === "FREE" ? (
<Badge className="ml-2" variant="default">
PRO
</Badge>
@@ -48,7 +42,7 @@ export default function AppCard(props: AppCardProps) {
<span>{props.rating} stars</span> <StarIcon className="ml-1 mt-0.5 h-4 w-4 text-yellow-600" />
<span className="pl-1 text-gray-500">{props.reviews} reviews</span>
</div> */}
<p className="mt-2 truncate text-sm text-gray-500">{props.description}</p>
<p className="mt-2 truncate text-sm text-gray-500">{props.app.description}</p>
</a>
</Link>
);
@@ -21,20 +21,10 @@ const TrendingAppsSlider = <T extends App>({ items }: { items: T[] }) => {
},
},
}}
renderItem={(app) => (
<AppCard
key={app.name}
name={app.name}
slug={app.slug}
description={app.description}
logo={app.logo}
rating={app.rating}
reviews={app.reviews}
isProOnly={app.isProOnly}
/>
)}
renderItem={(app) => <AppCard app={app} />}
/>
);
};
/** @deprecated use v2 instead, located at packages/ui/v2/core/apps */
export default TrendingAppsSlider;
+6 -5
View File
@@ -2,11 +2,10 @@ import React, { useEffect, useState } from "react";
import useDigitInput from "react-digit-input";
import { useFormContext } from "react-hook-form";
import { Input } from "@calcom/ui/form/fields";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Label, Input } from "@calcom/ui/form/fields";
import { useLocale } from "@lib/hooks/useLocale";
export default function TwoFactor() {
export default function TwoFactor({ center = true }) {
const [value, onChange] = useState("");
const { t } = useLocale();
const methods = useFormContext();
@@ -26,7 +25,9 @@ export default function TwoFactor() {
const className = "h-12 w-12 !text-xl text-center";
return (
<div className="mx-auto !mt-0 max-w-sm">
<div className={center ? "mx-auto !mt-0 max-w-sm" : "!mt-0 max-w-sm"}>
<Label className="mt-4"> {t("2fa_code")}</Label>
<p className="mb-4 text-sm text-gray-500">{t("2fa_enabled_instructions")}</p>
<input hidden type="hidden" value={value} {...methods.register("totpCode")} />
<div className="flex flex-row justify-between">
@@ -1,3 +1,7 @@
/**
* @deprecated
* use Component in "/packages/features/schedules/components/Schedule";
**/
import classNames from "classnames";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Controller, useFieldArray, useFormContext } from "react-hook-form";
@@ -192,6 +196,10 @@ const CopyTimes = ({ disabled, onApply }: { disabled: number[]; onApply: (select
);
};
/**
* @deprecated
* use Component in "/packages/features/schedules/components/Schedule";
**/
export const DayRanges = ({
name,
defaultValue = [defaultDayRange],
@@ -324,6 +332,10 @@ const ScheduleBlock = ({ name, day, weekday }: ScheduleBlockProps) => {
);
};
/**
* @deprecated
* use Component in "/packages/features/schedules/components/Schedule";
**/
const Schedule = ({ name }: { name: string }) => {
const { i18n } = useLocale();
return (
@@ -1,3 +1,7 @@
/**
* @deprecated modifications to this file should be v2 only
* Use `/packages/features/schedules/components/ScheduleListItem.tsx` instead
*/
import Link from "next/link";
import { Fragment } from "react";
@@ -9,6 +13,10 @@ import { Button } from "@calcom/ui";
import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@calcom/ui/Dropdown";
import { Icon } from "@calcom/ui/Icon";
/**
* @deprecated modifications to this file should be v2 only
* Use `/packages/features/schedules/components/ScheduleListItem.tsx` instead
*/
export function ScheduleListItem({
schedule,
deleteFunction,
@@ -37,7 +45,7 @@ export function ScheduleListItem({
<p className="mt-1 text-xs text-neutral-500">
{schedule.availability.map((availability: Availability) => (
<Fragment key={availability.id}>
{availabilityAsString(availability, i18n.language)}
{availabilityAsString(availability, { locale: i18n.language })}
<br />
</Fragment>
))}
@@ -45,6 +53,7 @@ export function ScheduleListItem({
</a>
</Link>
</div>
<Dropdown>
<DropdownMenuTrigger className="group mr-5 h-10 w-10 border border-transparent p-0 text-neutral-500 hover:border-gray-200">
<Icon.FiMoreHorizontal className="h-5 w-5 group-hover:text-gray-800" />
@@ -4,7 +4,7 @@ import { SkeletonText } from "@calcom/ui";
function SkeletonLoader() {
return (
<ul className="animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
<ul className="animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
@@ -0,0 +1,35 @@
import { getEventLocationType, locationKeyToString } from "@calcom/app-store/locations";
import { classNames } from "@calcom/lib";
import { Props } from "./pages/AvailabilityPage";
export function AvailableEventLocations({ locations }: { locations: Props["eventType"]["locations"] }) {
return locations.length ? (
<div>
<div className="dark:text-darkgray-600 mr-6 flex w-full flex-col space-y-2 break-words text-sm text-gray-600">
{locations.map((location) => {
const eventLocationType = getEventLocationType(location.type);
if (!eventLocationType) {
// It's possible that the location app got uninstalled
return null;
}
return (
<div key={location.type} className="flex flex-row items-center text-sm font-medium">
<img
src={eventLocationType.iconUrl}
className={classNames(
"mr-[10px] ml-[2px] h-4 w-4 opacity-70 dark:opacity-100 ",
!eventLocationType.iconUrl?.includes("api") ? "dark:invert" : ""
)}
alt={`${eventLocationType.label} icon`}
/>
<span key={location.type}>{locationKeyToString(location)} </span>
</div>
);
})}
</div>
</div>
) : (
<></>
);
}
+11 -7
View File
@@ -20,6 +20,7 @@ type AvailableTimesProps = {
seatsPerTimeSlot?: number | null;
slots?: Slot[];
isLoading: boolean;
ethSignature?: string;
};
const AvailableTimes: FC<AvailableTimesProps> = ({
@@ -31,6 +32,7 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
recurringCount,
timeFormat,
seatsPerTimeSlot,
ethSignature,
}) => {
const { t, i18n } = useLocale();
const router = useRouter();
@@ -43,9 +45,9 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
}, []);
return (
<div className="mt-8 flex flex-col px-4 text-center sm:mt-0 sm:w-1/3 sm:p-5 md:-mb-4 ">
<div className="dark:bg-darkgray-100 mt-8 flex flex-col px-4 text-center sm:mt-0 sm:w-1/3 sm:p-5 md:-mb-5">
<div className="mb-4 text-left text-base">
<span className="text-bookingdarker mb-8 w-1/2 break-words font-semibold text-gray-900 dark:text-white">
<span className="text-bookingdarker dark:text-darkgray-800 mb-8 w-1/2 break-words font-semibold text-gray-900">
{nameOfDay(i18n.language, Number(date.format("d")))}
</span>
<span className="text-bookinglight font-medium">
@@ -53,7 +55,7 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
{date.toDate().toLocaleString(i18n.language, { month: "long" })}
</span>
</div>
<div className="grid flex-grow grid-cols-2 gap-x-2 overflow-y-auto sm:block md:h-[364px]">
<div className="grid flex-grow grid-cols-1 gap-x-2 overflow-y-auto sm:block md:h-[364px]">
{slots.length > 0 &&
slots.map((slot) => {
type BookingURL = {
@@ -69,6 +71,7 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
slug: eventTypeSlug,
/** Treat as recurring only when a count exist and it's not a rescheduling workflow */
count: recurringCount && !rescheduleUid ? recurringCount : undefined,
ethSignature,
},
};
@@ -87,8 +90,8 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
{seatsPerTimeSlot && slot.attendees && slot.attendees >= seatsPerTimeSlot ? (
<div
className={classNames(
"text-primary-500 mb-2 block rounded-sm border bg-white py-4 font-medium opacity-25 dark:border-transparent dark:bg-gray-600 dark:text-neutral-200 ",
brand === "#fff" || brand === "#ffffff" ? "border-brandcontrast" : "border-brand"
"text-primary-500 dark:bg-darkgray-200 dark:text-darkgray-900 mb-2 block rounded-sm border bg-white py-2 font-medium opacity-25 dark:border-transparent ",
brand === "#fff" || brand === "#ffffff" ? "" : ""
)}>
{dayjs(slot.time).tz(timeZone()).format(timeFormat)}
{!!seatsPerTimeSlot && <p className="text-sm">{t("booking_full")}</p>}
@@ -97,8 +100,9 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
<Link href={bookingUrl} prefetch={false}>
<a
className={classNames(
"text-primary-500 hover:bg-brand hover:text-brandcontrast dark:hover:bg-darkmodebrand dark:hover:text-darkmodebrandcontrast mb-2 block rounded-sm border bg-white py-4 text-sm font-medium hover:text-white dark:border-transparent dark:bg-gray-600 dark:text-neutral-200 dark:hover:border-black",
brand === "#fff" || brand === "#ffffff" ? "border-brandcontrast" : "border-brand"
"text-primary-500 hover:border-gray-900 hover:bg-gray-50",
"dark:bg-darkgray-200 dark:hover:bg-darkgray-300 dark:hover:border-darkmodebrand mb-2 block rounded-md border bg-white py-2 text-sm font-medium dark:border-transparent dark:text-neutral-200",
brand === "#fff" || brand === "#ffffff" ? "" : ""
)}
data-testid="time">
{dayjs(slot.time).tz(timeZone()).format(timeFormat)}
+139 -85
View File
@@ -1,24 +1,22 @@
import { BookingStatus } from "@prisma/client";
import { useRouter } from "next/router";
import { useState } from "react";
import { useMutation } from "react-query";
import { EventLocationType, getEventLocationType } from "@calcom/app-store/locations";
import dayjs from "@calcom/dayjs";
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import showToast from "@calcom/lib/notification";
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
import { inferQueryInput, inferQueryOutput, trpc } from "@calcom/trpc/react";
import Button from "@calcom/ui/Button";
import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog";
import { Icon } from "@calcom/ui/Icon";
import { Tooltip } from "@calcom/ui/Tooltip";
import { TextArea } from "@calcom/ui/form/fields";
import Badge from "@calcom/ui/v2/core/Badge";
import Button from "@calcom/ui/v2/core/Button";
import { HttpError } from "@lib/core/http/error";
import useMeQuery from "@lib/hooks/useMeQuery";
import { linkValueToString } from "@lib/linkValueToString";
import { LocationType } from "@lib/location";
import { extractRecurringDates } from "@lib/parseDate";
import { EditLocationDialog } from "@components/dialog/EditLocationDialog";
@@ -43,39 +41,29 @@ function BookingListItem(booking: BookingItemProps) {
const router = useRouter();
const [rejectionReason, setRejectionReason] = useState<string>("");
const [rejectionDialogIsOpen, setRejectionDialogIsOpen] = useState(false);
const mutation = useMutation(
async (confirm: boolean) => {
let body = {
id: booking.id,
confirmed: confirm,
language: i18n.language,
reason: rejectionReason,
};
/**
* Only pass down the recurring event id when we need to confirm the entire series, which happens in
* the "Recurring" tab, to support confirming discretionally in the "Recurring" tab.
*/
if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) {
body = Object.assign({}, body, { recurringEventId: booking.recurringEventId });
}
const res = await fetch("/api/book/confirm", {
method: "PATCH",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
});
if (!res.ok) {
throw new HttpError({ statusCode: res.status });
}
const mutation = trpc.useMutation(["viewer.bookings.confirm"], {
onSuccess: () => {
setRejectionDialogIsOpen(false);
utils.invalidateQueries("viewer.bookings");
},
{
async onSettled() {
await utils.invalidateQueries(["viewer.bookings"]);
},
});
const bookingConfirm = async (confirm: boolean) => {
let body = {
bookingId: booking.id,
confirmed: confirm,
reason: rejectionReason,
};
/**
* Only pass down the recurring event id when we need to confirm the entire series, which happens in
* the "Recurring" tab, to support confirming discretionally in the "Recurring" tab.
*/
if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) {
body = Object.assign({}, body, { recurringEventId: booking.recurringEventId });
}
);
mutation.mutate(body);
};
const isUpcoming = new Date(booking.endTime) >= new Date();
const isCancelled = booking.status === BookingStatus.CANCELLED;
const isConfirmed = booking.status === BookingStatus.ACCEPTED;
@@ -102,7 +90,7 @@ function BookingListItem(booking: BookingItemProps) {
? t("confirm_all")
: t("confirm"),
onClick: () => {
mutation.mutate(true);
bookingConfirm(true);
},
icon: Icon.FiCheck,
disabled: mutation.isLoading,
@@ -182,17 +170,10 @@ function BookingListItem(booking: BookingItemProps) {
},
});
const saveLocation = (newLocationType: LocationType, details: { [key: string]: string }) => {
const saveLocation = (newLocationType: EventLocationType["type"], details: { [key: string]: string }) => {
let newLocation = newLocationType as string;
if (
newLocationType === LocationType.InPerson ||
newLocationType === LocationType.Link ||
newLocationType === LocationType.UserPhone ||
newLocationType === LocationType.Riverside ||
newLocationType === LocationType.Around ||
newLocationType === LocationType.Whereby ||
newLocationType === LocationType.Ping
) {
const eventLocationType = getEventLocationType(newLocationType);
if (eventLocationType?.organizerInputType) {
newLocation = details[Object.keys(details)[0]];
}
setLocationMutation.mutate({ bookingId: booking.id, newLocation });
@@ -201,31 +182,16 @@ function BookingListItem(booking: BookingItemProps) {
// Calculate the booking date(s) and setup recurring event data to show
let recurringStrings: string[] = [];
let recurringDates: Date[] = [];
const today = new Date();
if (booking.recurringBookings && booking.eventType.recurringEvent?.freq !== undefined) {
[recurringStrings, recurringDates] = extractRecurringDates(
booking.recurringBookings,
user?.timeZone,
i18n
);
if (booking.status === BookingStatus.PENDING) {
// Only take into consideration next up instances if booking is confirmed
recurringDates = recurringDates.filter((aDate) => aDate >= today);
recurringStrings = recurringDates.map((_, key) => recurringStrings[key]);
}
}
let location = booking.location || "";
if (location.includes("integration")) {
if (booking.status === BookingStatus.CANCELLED || booking.status === BookingStatus.REJECTED) {
location = t("web_conference");
} else if (isConfirmed) {
location = linkValueToString(booking.location, t);
} else {
location = t("web_conferencing_details_to_follow");
}
}
const location = booking.location || "";
const onClick = () => {
router.push({
@@ -287,7 +253,7 @@ function BookingListItem(booking: BookingItemProps) {
<Button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate(false);
bookingConfirm(false);
}}>
{t("rejection_confirmation")}
</Button>
@@ -296,7 +262,7 @@ function BookingListItem(booking: BookingItemProps) {
</Dialog>
<tr className="flex hover:bg-neutral-50">
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-64" onClick={onClick}>
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-28" onClick={onClick}>
<div className="cursor-pointer py-4">
<div className="text-sm leading-6 text-gray-900">{startTime}</div>
<div className="text-sm text-gray-500">
@@ -337,19 +303,23 @@ function BookingListItem(booking: BookingItemProps) {
</div>
</div>
</td>
<td className={"flex-1 ltr:pl-4 rtl:pr-4" + (isRejected ? " line-through" : "")} onClick={onClick}>
<td className={"flex-1 px-4" + (isRejected ? " line-through" : "")} onClick={onClick}>
<div className="cursor-pointer py-4">
<div className="sm:hidden">
{isPending && <Tag className="mb-2 ltr:mr-2 rtl:ml-2">{t("unconfirmed")}</Tag>}
{!!booking?.eventType?.price && !booking.paid && (
<Tag className="mb-2 ltr:mr-2 rtl:ml-2">Pending payment</Tag>
)}
<div className="text-sm font-medium text-gray-900">
{startTime}:{" "}
<small className="text-sm text-gray-500">
{dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
</small>
</div>
{isPending && (
<Badge variant="orange" className="mb-2 ltr:mr-2 rtl:ml-2">
{t("unconfirmed")}
</Badge>
)}
{!!booking?.eventType?.price && !booking.paid && (
<Badge variant="orange" className="mb-2 ltr:mr-2 rtl:ml-2">
{t("pending_payment")}
</Badge>
)}
<div className="text-sm font-medium text-gray-900">
{startTime}:{" "}
<small className="text-sm text-gray-500">
{dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
</small>
</div>
<div
title={booking.title}
@@ -357,8 +327,10 @@ function BookingListItem(booking: BookingItemProps) {
"max-w-56 truncate text-sm font-medium leading-6 text-neutral-900 md:max-w-max",
isCancelled ? "line-through" : ""
)}>
{booking.eventType?.team && <strong>{booking.eventType.team.name}: </strong>}
{booking.title}
<span> </span>
{booking.eventType?.team && <Badge variant="gray">{booking.eventType.team.name}</Badge>}
{!!booking?.eventType?.price && !booking.paid && (
<Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">Pending payment</Tag>
)}
@@ -371,14 +343,12 @@ function BookingListItem(booking: BookingItemProps) {
&quot;{booking.description}&quot;
</div>
)}
{booking.attendees.length !== 0 && (
<a
className="text-sm text-gray-900 hover:text-blue-500"
href={"mailto:" + booking.attendees[0].email}
onClick={(e) => e.stopPropagation()}>
{booking.attendees[0].email}
</a>
<DisplayAttendees
attendees={booking.attendees}
user={booking.user}
currentEmail={user?.email}
/>
)}
{isCancelled && booking.rescheduled && (
<div className="mt-2 inline-block text-left text-sm md:hidden">
@@ -407,6 +377,90 @@ function BookingListItem(booking: BookingItemProps) {
);
}
interface UserProps {
id: number;
name: string | null;
email: string;
}
const FirstAttendee = ({
user,
currentEmail,
}: {
user: UserProps;
currentEmail: string | null | undefined;
}) => {
return user.email === currentEmail ? (
<div className="inline-block">You</div>
) : (
<a
key={user.email}
className=" hover:text-blue-500"
href={"mailto:" + user.email}
onClick={(e) => e.stopPropagation()}>
{user.name}
</a>
);
};
const Attendee: React.FC<{ email: string; children: React.ReactNode }> = ({ email, children }) => {
return (
<a className=" hover:text-blue-500" href={"mailto:" + email} onClick={(e) => e.stopPropagation()}>
{children}
</a>
);
};
interface AttendeeProps {
name: string;
email: string;
}
const DisplayAttendees = ({
attendees,
user,
currentEmail,
}: {
attendees: AttendeeProps[];
user: UserProps | null;
currentEmail: string | null | undefined;
}) => {
if (attendees.length === 1) {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>&nbsp;and&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
</div>
);
} else if (attendees.length === 2) {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>,&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
<div className="inline-block text-sm text-gray-900">&nbsp;and&nbsp;</div>
<Attendee email={attendees[1].email}>{attendees[1].name}</Attendee>
</div>
);
} else {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>,&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
<span>&nbsp;&&nbsp;</span>
<Tooltip
content={attendees.slice(1).map((attendee, key) => (
<p key={key}>{attendee.name}</p>
))}>
<div className="inline-block">{attendees.length - 1} more</div>
</Tooltip>
</div>
);
}
};
const Tag = ({ children, className = "" }: React.PropsWithChildren<{ className?: string }>) => {
return (
<span
@@ -4,7 +4,7 @@ import { SkeletonText } from "@calcom/ui";
function SkeletonLoader() {
return (
<ul className="mt-6 animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
<ul className="animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:overflow-hidden">
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
@@ -16,7 +16,7 @@ export default SkeletonLoader;
function SkeletonItem() {
return (
<li className="group flex w-full items-center justify-between px-2 py-4 sm:px-6">
<li className="group flex w-full items-center justify-between px-4 py-4 sm:px-6">
<div className="flex-grow truncate text-sm">
<div className="flex">
<div className="flex flex-col space-y-2">
+2 -2
View File
@@ -1,8 +1,8 @@
import { FC, useEffect, useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import Switch from "@calcom/ui/Switch";
import TimezoneSelect, { ITimezoneOption } from "@calcom/ui/form/TimezoneSelect";
import { Switch } from "@calcom/ui/v2";
import { is24h, timeZone } from "../../lib/clock";
@@ -33,7 +33,7 @@ const TimeOptions: FC<Props> = ({ onToggle24hClock, onSelectTimeZone, timeFormat
};
return selectedTimeZone !== "" ? (
<div className="max-w-80 absolute z-10 w-full rounded-sm rounded border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm dark:border-0 dark:bg-gray-700">
<div className="max-w-80 dark:border-darkgray-300 dark:bg-darkgray-200 absolute z-10 w-full rounded-sm border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm">
<div className="mb-4 flex">
<div className="text-sm font-medium text-gray-600 dark:text-white">{t("time_options")}</div>
<div className="ml-auto flex items-center">
+1 -1
View File
@@ -14,7 +14,7 @@ export const UserAvatars = ({
const showMembers = !users.find((user) => user.name === profile.name) && props.showMembers;
return (
<AvatarGroup
border="border-2 dark:border-gray-800 border-white"
border="border-2 dark:border-darkgray-100 border-white"
items={
[
{ image: profile.image, alt: profile.name, title: profile.name },
@@ -4,11 +4,11 @@ import { SchedulingType } from "@prisma/client";
import * as Collapsible from "@radix-ui/react-collapsible";
import { TFunction } from "next-i18next";
import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react";
import { useReducer, useEffect, useMemo, useState } from "react";
import { Toaster } from "react-hot-toast";
import { FormattedNumber, IntlProvider } from "react-intl";
import { z } from "zod";
import { AppStoreLocationType, LocationObject, LocationType } from "@calcom/app-store/locations";
import dayjs, { Dayjs } from "@calcom/dayjs";
import {
useEmbedNonStylesConfig,
@@ -16,7 +16,6 @@ import {
useIsBackgroundTransparent,
useIsEmbed,
} from "@calcom/embed-core/embed-iframe";
import { useContracts } from "@calcom/features/ee/web3/contexts/contractsContext";
import CustomBranding from "@calcom/lib/CustomBranding";
import classNames from "@calcom/lib/classNames";
import { WEBSITE_URL } from "@calcom/lib/constants";
@@ -29,13 +28,14 @@ import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
import { localStorage } from "@calcom/lib/webstorage";
import { trpc } from "@calcom/trpc/react";
import { Icon } from "@calcom/ui/Icon";
import DatePicker from "@calcom/ui/booker/DatePicker";
import DatePicker from "@calcom/ui/v2/modules/booker/DatePicker";
import { timeZone as localStorageTimeZone } from "@lib/clock";
// import { timeZone } from "@lib/clock";
import { useExposePlanGlobally } from "@lib/hooks/useExposePlanGlobally";
import { isBrandingHidden } from "@lib/isBrandingHidden";
import Gates, { Gate, GateState } from "@components/Gates";
import AvailableTimes from "@components/booking/AvailableTimes";
import TimeOptions from "@components/booking/TimeOptions";
import { UserAvatars } from "@components/booking/UserAvatars";
@@ -46,41 +46,7 @@ import PoweredByCal from "@components/ui/PoweredByCal";
import type { AvailabilityPageProps } from "../../../pages/[user]/[type]";
import type { DynamicAvailabilityPageProps } from "../../../pages/d/[link]/[slug]";
import type { AvailabilityTeamPageProps } from "../../../pages/team/[slug]/[type]";
type Props = AvailabilityTeamPageProps | AvailabilityPageProps | DynamicAvailabilityPageProps;
export const locationKeyToString = (location: LocationObject, t: TFunction) => {
switch (location.type) {
case LocationType.InPerson:
return location.address || "In Person"; // If disabled address won't exist on the object
case LocationType.Link:
case LocationType.Ping:
case LocationType.Riverside:
case LocationType.Around:
case LocationType.Whereby:
return location.link || "Link"; // If disabled link won't exist on the object
case LocationType.Phone:
return t("your_number");
case LocationType.UserPhone:
return t("phone_call");
case LocationType.GoogleMeet:
return "Google Meet";
case LocationType.Zoom:
return "Zoom";
case LocationType.Daily:
return "Cal Video";
case LocationType.Jitsi:
return "Jitsi";
case LocationType.Huddle01:
return "Huddle Video";
case LocationType.Tandem:
return "Tandem";
case LocationType.Teams:
return "Microsoft Teams";
default:
return null;
}
};
import { AvailableEventLocations } from "../AvailableEventLocations";
const GoBackToPreviousPage = ({ t }: { t: TFunction }) => {
const router = useRouter();
@@ -91,7 +57,7 @@ const GoBackToPreviousPage = ({ t }: { t: TFunction }) => {
return (
<div className="flex h-full flex-col justify-end">
<button title={t("profile")} onClick={() => router.replace(`${WEBSITE_URL}/${slug}`)}>
<Icon.FiArrowLeft className="h-4 w-4 text-black transition-opacity hover:cursor-pointer dark:text-white" />
<Icon.FiArrowLeft className="dark:text-darkgray-600 h-4 w-4 text-black transition-opacity hover:cursor-pointer" />
<p className="sr-only">Go Back</p>
</button>
</div>
@@ -147,6 +113,7 @@ const SlotPicker = ({
users,
seatsPerTimeSlot,
weekStart = 0,
ethSignature,
}: {
eventType: Pick<EventType, "id" | "schedulingType" | "slug">;
timeFormat: string;
@@ -155,6 +122,7 @@ const SlotPicker = ({
recurringEventCount?: number;
users: string[];
weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
ethSignature?: string;
}) => {
const [selectedDate, setSelectedDate] = useState<Dayjs>();
const [browsingDate, setBrowsingDate] = useState<Dayjs>();
@@ -208,9 +176,9 @@ const SlotPicker = ({
<DatePicker
isLoading={isLoading}
className={classNames(
"mt-8 w-full sm:mt-0 sm:min-w-[455px]",
"mt-8 w-full px-4 sm:mt-0 sm:min-w-[455px] md:px-5",
selectedDate
? "border-gray-200 sm:w-1/2 sm:border-r sm:p-4 sm:pr-6 sm:dark:border-gray-700 md:w-1/3 "
? "sm:dark:border-darkgray-200 border-gray-200 sm:w-1/2 sm:border-r sm:p-4 sm:pr-6 md:w-1/3 "
: "sm:p-4"
)}
includedDates={Object.keys(slots).filter((k) => slots[k].length > 0)}
@@ -236,6 +204,7 @@ const SlotPicker = ({
eventTypeSlug={eventType.slug}
seatsPerTimeSlot={seatsPerTimeSlot}
recurringCount={recurringEventCount}
ethSignature={ethSignature}
/>
)}
</>
@@ -272,15 +241,15 @@ function TimezoneDropdown({
};
return (
<Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}>
<Collapsible.Trigger className="min-w-32 text-bookinglight mb-1 -ml-2 px-2 py-1 text-left dark:text-white">
<p className="py-1 text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen} className="flex">
<Collapsible.Trigger className="min-w-32 dark:text-darkgray-600 mb-2 -ml-2 px-2 text-left text-gray-600">
<p className="text-sm font-medium">
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-[2px] inline-block h-4 w-4" />
{timeZone}
{isTimeOptionsOpen ? (
<Icon.FiChevronUp className="ml-1 -mt-1 inline-block h-4 w-4 text-gray-500" />
<Icon.FiChevronUp className="ml-1 inline-block h-4 w-4 " />
) : (
<Icon.FiChevronDown className="ml-1 -mt-1 inline-block h-4 w-4 text-gray-500" />
<Icon.FiChevronDown className="ml-1 inline-block h-4 w-4 " />
)}
</p>
</Collapsible.Trigger>
@@ -318,6 +287,8 @@ const useRouterQuery = <T extends string>(name: T) => {
} & { setQuery: typeof setQuery };
};
export type Props = AvailabilityTeamPageProps | AvailabilityPageProps | DynamicAvailabilityPageProps;
const AvailabilityPage = ({ profile, eventType }: Props) => {
const router = useRouter();
const isEmbed = useIsEmbed();
@@ -325,7 +296,6 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
const { rescheduleUid } = query;
useTheme(profile.theme);
const { t } = useLocale();
const { contracts } = useContracts();
const availabilityDatePickerEmbedStyles = useEmbedStyles("availabilityDatePicker");
const shouldAlignCentrallyInEmbed = useEmbedNonStylesConfig("align") !== "left";
const shouldAlignCentrally = !isEmbed || shouldAlignCentrallyInEmbed;
@@ -334,6 +304,13 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
const [timeZone, setTimeZone] = useState<string>();
const [timeFormat, setTimeFormat] = useState(detectBrowserTimeFormat);
const [isAvailableTimesVisible, setIsAvailableTimesVisible] = useState<boolean>();
const [gateState, gateDispatcher] = useReducer(
(state: GateState, newState: Partial<GateState>) => ({
...state,
...newState,
}),
{}
);
useEffect(() => {
setTimeZone(localStorageTimeZone() || dayjs.tz.guess());
@@ -346,15 +323,6 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
// TODO: Improve this;
useExposePlanGlobally(eventType.users.length === 1 ? eventType.users[0].plan : "PRO");
// TODO: this needs to be extracted elsewhere
useEffect(() => {
if (eventType.metadata.smartContractAddress) {
const eventOwner = eventType.users[0];
if (!contracts[(eventType.metadata.smartContractAddress || null) as number])
router.replace(`/${eventOwner.username}`);
}
}, [contracts, eventType.metadata.smartContractAddress, eventType.users, router]);
const [recurringEventCount, setRecurringEventCount] = useState(eventType.recurringEvent?.count);
const telemetry = useTelemetry();
@@ -369,7 +337,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
}, [telemetry]);
// get dynamic user list here
const userList = eventType.users.map((user) => user.username).filter(notEmpty);
const userList = eventType.users ? eventType.users.map((user) => user.username).filter(notEmpty) : [];
// Recurring event sidebar requires more space
const maxWidth = isAvailableTimesVisible
? recurringEventCount
@@ -393,8 +361,16 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
if (rawSlug.length > 1) rawSlug.pop(); //team events have team name as slug, but user events have [user]/[type] as slug.
const slug = rawSlug.join("/");
// Define conditional gates here
const gates = [
// Rainbow gate is only added if the event has both a `blockchainId` and a `smartContractAddress`
eventType.metadata && eventType.metadata.blockchainId && eventType.metadata.smartContractAddress
? ("rainbow" as Gate)
: undefined,
];
return (
<>
<Gates gates={gates} metadata={eventType.metadata} dispatch={gateDispatcher}>
<HeadSeo
title={`${rescheduleUid ? t("reschedule") : ""} ${eventType.title} | ${profile.name}`}
description={`${rescheduleUid ? t("reschedule") : ""} ${eventType.title}`}
@@ -417,8 +393,8 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
<div
style={availabilityDatePickerEmbedStyles}
className={classNames(
isBackgroundTransparent ? "" : "bg-white dark:bg-gray-800 sm:dark:border-gray-600",
"border-bookinglightest rounded-md md:border",
isBackgroundTransparent ? "" : "dark:bg-darkgray-100 sm:dark:border-darkgray-300 bg-white",
"border-bookinglightest overflow-hidden rounded-md md:border",
isEmbed ? "mx-auto" : maxWidth
)}>
{/* mobile: details */}
@@ -432,65 +408,36 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
truncateAfter={5}
/>
<div className="mt-4">
<p className="break-words text-sm font-medium text-black dark:text-white">{profile.name}</p>
<div className="mt-2 gap-2 dark:text-gray-100">
<h1 className="text-bookingdark mb-4 break-words text-xl font-semibold dark:text-white">
<div className="dark:text-darkgray-900 mt-2 gap-2">
<p className="break-words text-sm font-medium text-gray-600 dark:text-gray-300">
{profile.name}
</p>
<h1 className="text-bookingdark dark:text-darkgray-900 mb-4 break-words text-xl font-semibold">
{eventType.title}
</h1>
<div className="flex flex-col space-y-2">
<div className="flex flex-col space-y-3">
{eventType?.description && (
<div className="flex py-1 text-sm font-medium text-gray-600 dark:text-white">
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
<div>
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<p className="text-gray-600 dark:text-white">
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<p className="dark:text-darkgray-600 dark:text-darkgray-600 text-gray-600">
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{t("requires_confirmation")}
</p>
)}
{eventType.locations.length === 1 && (
<p className="text-gray-600 dark:text-white">
{Object.values(AppStoreLocationType).includes(
eventType.locations[0].type as unknown as AppStoreLocationType
) ? (
<Icon.FiVideo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
) : (
<Icon.FiMapPin className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
)}
{locationKeyToString(eventType.locations[0], t)}
</p>
)}
{eventType.locations.length > 1 && (
<div className="flex-warp flex text-gray-600 dark:text-white">
<div className="mr-[10px] ml-[2px] -mt-1 ">
<Icon.FiMapPin className="inline-block h-4 w-4 text-gray-500" />
</div>
<p>
{eventType.locations.map((el, i, arr) => {
return (
<span key={el.type}>
{locationKeyToString(el, t)}{" "}
{arr.length - 1 !== i && (
<span className="font-light"> {t("or_lowercase")} </span>
)}
</span>
);
})}
</p>
</div>
)}
<p className="text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-500" />
<AvailableEventLocations locations={eventType.locations} />
<p className="dark:text-darkgray-600 text-gray-600">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
{eventType.price > 0 && (
<div className="text-gray-600 dark:text-white">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 dark:text-gray-500" />
<div className="dark:text-darkgray-600 text-gray-600">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
@@ -501,7 +448,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</div>
)}
{!rescheduleUid && eventType.recurringEvent && (
<div className="flex items-center text-gray-600 dark:text-white">
<div className="dark:text-darkgray-600 flex items-center text-gray-600">
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-1 ml-[2px] inline-block h-4 w-4 shrink-0 text-gray-500" />
<div>
<p className="mb-1 -ml-2 inline px-2 py-1">
@@ -511,13 +458,13 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
type="number"
min="1"
max={eventType.recurringEvent.count}
className="w-15 h-7 rounded-sm border-gray-300 bg-white text-sm text-gray-600 [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500 dark:bg-gray-600 dark:text-white"
className="w-15 dark:text-darkgray-600 h-7 rounded-sm border-gray-300 bg-white text-sm text-gray-600 [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500 dark:bg-gray-600"
defaultValue={eventType.recurringEvent.count}
onChange={(event) => {
setRecurringEventCount(parseInt(event?.target.value));
}}
/>
<p className="inline text-gray-600 dark:text-white">
<p className="dark:text-darkgray-600 inline text-gray-600 ">
{t("occurrence", {
count: recurringEventCount,
})}
@@ -531,11 +478,11 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
{/* Temp disabled booking?.startTime && rescheduleUid && (
<div>
<p
className="mt-8 text-gray-600 dark:text-white"
className="mt-8 text-gray-600 dark:text-darkgray-600"
data-testid="former_time_p_mobile">
{t("former_time")}
</p>
<p className="text-gray-500 line-through dark:text-white">
<p className="text-gray-500 line-through dark:text-darkgray-600">
<CalendarIcon className="mr-[10px] -mt-1 inline-block h-4 w-4 text-gray-500" />
{typeof booking.startTime === "string" &&
parseDate(dayjs(booking.startTime), i18n)}
@@ -552,7 +499,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
<div className="overflow-hidden sm:flex">
<div
className={
"hidden overflow-hidden border-gray-200 p-5 sm:border-r sm:dark:border-gray-700 md:flex md:flex-col " +
"sm:dark:border-darkgray-200 hidden overflow-hidden border-gray-200 p-5 sm:border-r md:flex md:flex-col " +
(isAvailableTimesVisible ? "sm:w-1/3" : recurringEventCount ? "sm:w-2/3" : "sm:w-1/2")
}>
<UserAvatars
@@ -562,68 +509,37 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
size={10}
truncateAfter={3}
/>
<h2 className="mt-2 break-words text-sm font-medium text-gray-500 dark:text-gray-300">
<h2 className="break-words text-sm font-medium text-gray-600 dark:text-gray-300 lg:mt-2">
{profile.name}
</h2>
<h1 className="font-cal mb-6 break-words text-2xl text-gray-900 dark:text-white">
<h1 className="font-cal dark:text-darkgray-900 mb-6 break-words text-2xl text-gray-900 ">
{eventType.title}
</h1>
<div className="flex flex-col space-y-2">
<div className="dark:text-darkgray-600 flex flex-col space-y-3 text-sm font-medium text-gray-600">
{eventType?.description && (
<div className="flex py-1 text-sm font-medium text-gray-600 dark:text-white">
<div className="flex ">
<div>
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<div className="flex items-center text-sm font-medium text-gray-600 dark:text-white">
<div className="flex items-center">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
</div>
{t("requires_confirmation")}
</div>
)}
{eventType.locations.length === 1 && (
<p className="py-1 text-sm font-medium text-gray-600 dark:text-white">
{Object.values(AppStoreLocationType).includes(
eventType.locations[0].type as unknown as AppStoreLocationType
) ? (
<Icon.FiVideo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
) : (
<Icon.FiMapPin className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
)}
{locationKeyToString(eventType.locations[0], t)}
</p>
)}
{eventType.locations.length > 1 && (
<div className="flex-warp flex items-center font-medium text-gray-600 dark:text-white">
<div className="mr-[10px] ml-[2px] -mt-1 ">
<Icon.FiMapPin className="inline-block h-4 w-4 text-gray-500" />
</div>
<p className="py-1 text-sm font-medium text-gray-600 dark:text-white">
{eventType.locations.map((el, i, arr) => {
return (
<span key={el.type}>
{locationKeyToString(el, t)}{" "}
{arr.length - 1 !== i && (
<span className="text-sm font-light"> {t("or_lowercase")} </span>
)}
</span>
);
})}
</p>
</div>
)}
<p className="py-1 text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-500" />
<AvailableEventLocations locations={eventType.locations} />
<p className="text-sm font-medium">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
{!rescheduleUid && eventType.recurringEvent && (
<div className="flex items-center text-gray-600 dark:text-white">
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-1 ml-[2px] inline-block h-4 w-4 text-gray-500" />
<div className="flex items-start text-sm font-medium">
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-[7px] ml-[2px] inline-block h-4 w-4 " />
<div>
<p className="mb-1 -ml-2 inline px-2 py-1">
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
@@ -632,13 +548,13 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
type="number"
min="1"
max={eventType.recurringEvent.count}
className="w-15 h-7 rounded-sm border-gray-300 bg-white text-sm text-gray-600 [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500 dark:bg-gray-600 dark:text-white"
className="w-15 dark:bg-darkgray-200 h-7 rounded-sm border-gray-300 bg-white text-sm font-medium [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500"
defaultValue={eventType.recurringEvent.count}
onChange={(event) => {
setRecurringEventCount(parseInt(event?.target.value));
}}
/>
<p className="inline text-gray-600 dark:text-white">
<p className="inline">
{t("occurrence", {
count: recurringEventCount,
})}
@@ -647,8 +563,8 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</div>
)}
{eventType.price > 0 && (
<p className="-ml-2 px-2 py-1 text-gray-600 dark:text-white">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<p className="-ml-2 px-2 text-sm font-medium ">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
@@ -666,11 +582,11 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
{/* Temporarily disabled - booking?.startTime && rescheduleUid && (
<div>
<p
className="mt-4 mb-3 text-gray-600 dark:text-white"
className="mt-4 mb-3 text-gray-600 dark:text-darkgray-600"
data-testid="former_time_p_desktop">
{t("former_time")}
</p>
<p className="text-gray-500 line-through dark:text-white">
<p className="text-gray-500 line-through dark:text-darkgray-600">
<CalendarIcon className="mr-[10px] -mt-1 inline-block h-4 w-4 text-gray-500" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
</p>
@@ -691,13 +607,15 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
users={userList}
seatsPerTimeSlot={eventType.seatsPerTimeSlot || undefined}
recurringEventCount={recurringEventCount}
ethSignature={gateState.rainbowToken}
/>
</div>
</div>
{(!eventType.users[0] || !isBrandingHidden(eventType.users[0])) && !isEmbed && <PoweredByCal />}
</main>
</div>
</>
<Toaster position="bottom-right" />
</Gates>
);
};
+198 -218
View File
@@ -5,7 +5,7 @@ import { isValidPhoneNumber } from "libphonenumber-js";
import { useSession } from "next-auth/react";
import Head from "next/head";
import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useState, useReducer } from "react";
import { Controller, useForm, useWatch } from "react-hook-form";
import { FormattedNumber, IntlProvider } from "react-intl";
import { ReactMultiEmail } from "react-multi-email";
@@ -13,14 +13,20 @@ import { useMutation } from "react-query";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
import {
locationKeyToString,
getEventLocationValue,
getEventLocationType,
EventLocationType,
} from "@calcom/app-store/locations";
import { createPaymentLink } from "@calcom/app-store/stripepayment/lib/client";
import { LocationObject, LocationType } from "@calcom/core/location";
import dayjs from "@calcom/dayjs";
import {
useEmbedNonStylesConfig,
useIsBackgroundTransparent,
useIsEmbed,
} from "@calcom/embed-core/embed-iframe";
import { useContracts } from "@calcom/features/ee/web3/contexts/contractsContext";
import CustomBranding from "@calcom/lib/CustomBranding";
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -37,36 +43,26 @@ import { EmailInput, Form } from "@calcom/ui/form/fields";
import { asStringOrNull } from "@lib/asStringOrNull";
import { timeZone } from "@lib/clock";
import { ensureArray } from "@lib/ensureArray";
import { LocationObject, LocationType } from "@lib/location";
import createBooking from "@lib/mutations/bookings/create-booking";
import createRecurringBooking from "@lib/mutations/bookings/create-recurring-booking";
import { parseDate, parseRecurringDates } from "@lib/parseDate";
import slugify from "@lib/slugify";
import Gates, { Gate, GateState } from "@components/Gates";
import { UserAvatars } from "@components/booking/UserAvatars";
import EventTypeDescriptionSafeHTML from "@components/eventtype/EventTypeDescriptionSafeHTML";
import { BookPageProps } from "../../../pages/[user]/book";
import { HashLinkPageProps } from "../../../pages/d/[link]/book";
import { TeamBookingPageProps } from "../../../pages/team/[slug]/book";
declare global {
// eslint-disable-next-line no-var
var web3: {
currentProvider: {
selectedAddress: string;
};
};
}
type BookingPageProps = (BookPageProps | TeamBookingPageProps | HashLinkPageProps) & {
locationLabels: Record<LocationType, string>;
};
type BookingPageProps = BookPageProps | TeamBookingPageProps | HashLinkPageProps;
type BookingFormValues = {
name: string;
email: string;
notes?: string;
locationType?: LocationType;
locationType?: EventLocationType["type"];
guests?: string[];
phone?: string;
hostPhoneNumber?: string; // Maybe come up with a better way to name this to distingish between two types of phone numbers
@@ -83,7 +79,6 @@ const BookingPage = ({
profile,
isDynamicGroupBooking,
recurringEventCount,
locationLabels,
hasHashedBookingLink,
hashedLink,
}: BookingPageProps) => {
@@ -92,10 +87,16 @@ const BookingPage = ({
const shouldAlignCentrallyInEmbed = useEmbedNonStylesConfig("align") !== "left";
const shouldAlignCentrally = !isEmbed || shouldAlignCentrallyInEmbed;
const router = useRouter();
const { contracts } = useContracts();
const { data: session } = useSession();
const isBackgroundTransparent = useIsBackgroundTransparent();
const telemetry = useTelemetry();
const [gateState, gateDispatcher] = useReducer(
(state: GateState, newState: Partial<GateState>) => ({
...state,
...newState,
}),
{}
);
useEffect(() => {
if (top !== window) {
@@ -108,15 +109,6 @@ const BookingPage = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (eventType.metadata.smartContractAddress) {
const eventOwner = eventType.users[0];
if (!contracts[(eventType.metadata.smartContractAddress || null) as number])
router.replace(`/${eventOwner.username}`);
}
}, [contracts, eventType.metadata.smartContractAddress, eventType.users, router]);
const mutation = useMutation(createBooking, {
onSuccess: async (responseData) => {
const { id, attendees, paymentUid } = responseData;
@@ -132,16 +124,6 @@ const BookingPage = ({
);
}
const location = (function humanReadableLocation(location) {
if (!location) {
return;
}
if (location.includes("integration")) {
return t("web_conferencing_details_to_follow");
}
return location;
})(responseData.location);
return router.push({
pathname: "/success",
query: {
@@ -152,7 +134,7 @@ const BookingPage = ({
reschedule: !!rescheduleUid,
name: attendees[0].name,
email: attendees[0].email,
location,
location: responseData.location,
eventName: profile.eventName || "",
bookingId: id,
isSuccessBookingPage: true,
@@ -198,9 +180,6 @@ const BookingPage = ({
const date = asStringOrNull(router.query.date);
const [guestToggle, setGuestToggle] = useState(booking && booking.attendees.length > 1);
const eventTypeDetail = { isWeb3Active: false, ...eventType };
// it would be nice if Prisma at some point in the future allowed for Json<Location>; as of now this is not the case.
const locations: LocationObject[] = useMemo(
() => (eventType.locations as LocationObject[]) || [],
@@ -213,7 +192,6 @@ const BookingPage = ({
}
}, [router.query.guest]);
const locationInfo = (type: LocationType) => locations.find((location) => location.type === type);
const loggedInIsOwner = eventType?.users[0]?.id === session?.user?.id;
const guestListEmails = !isDynamicGroupBooking
? booking?.attendees.slice(1).map((attendee) => attendee.email)
@@ -264,6 +242,7 @@ const BookingPage = ({
guests: guestListEmails,
notes: booking.description || "",
rescheduleReason: "",
smsReminderNumber: booking.smsReminderNumber || undefined,
customInputs: eventType.customInputs.reduce(
(customInputs, input) => ({
...customInputs,
@@ -296,12 +275,12 @@ const BookingPage = ({
resolver: zodResolver(bookingFormSchema), // Since this isn't set to strict we only validate the fields in the schema
});
const selectedLocation = useWatch({
const selectedLocationType = useWatch({
control: bookingForm.control,
name: "locationType",
defaultValue: ((): LocationType | undefined => {
defaultValue: ((): EventLocationType["type"] | undefined => {
if (router.query.location) {
return router.query.location as LocationType;
return router.query.location as EventLocationType["type"];
}
if (locations.length === 1) {
return locations[0]?.type;
@@ -309,40 +288,13 @@ const BookingPage = ({
})(),
});
const getLocationValue = (
booking: Pick<BookingFormValues, "locationType" | "phone" | "hostPhoneNumber">
) => {
const { locationType } = booking;
switch (locationType) {
case LocationType.Phone: {
return booking.phone || "";
}
case LocationType.InPerson: {
return locationInfo(locationType)?.address || "";
}
case LocationType.Link: {
return locationInfo(locationType)?.link || "";
}
case LocationType.UserPhone: {
return locationInfo(locationType)?.hostPhoneNumber || "";
}
case LocationType.Around: {
return locationInfo(locationType)?.link || "";
}
case LocationType.Riverside: {
return locationInfo(locationType)?.link || "";
}
case LocationType.Whereby: {
return locationInfo(locationType)?.link || "";
}
case LocationType.Ping: {
return locationInfo(locationType)?.link || "";
}
// Catches all other location types, such as Google Meet, Zoom etc.
default:
return selectedLocation || "";
}
};
const selectedLocation = getEventLocationType(selectedLocationType);
const AttendeeInput =
selectedLocation?.attendeeInputType === "text"
? "input"
: selectedLocation?.attendeeInputType === "phone"
? PhoneInput
: null;
// Calculate the booking date(s)
let recurringStrings: string[] = [],
@@ -378,20 +330,11 @@ const BookingPage = ({
{}
);
let web3Details: Record<"userWallet" | "userSignature", string> | undefined;
if (eventTypeDetail.metadata.smartContractAddress) {
web3Details = {
userWallet: window.web3.currentProvider.selectedAddress,
userSignature: contracts[(eventTypeDetail.metadata.smartContractAddress || null) as number],
};
}
if (recurringDates.length) {
// Identify set of bookings to one intance of recurring event to support batch changes
const recurringEventId = uuidv4();
const recurringBookings = recurringDates.map((recurringDate) => ({
...booking,
web3Details,
start: dayjs(recurringDate).format(),
end: dayjs(recurringDate).add(eventType.length, "minute").format(),
eventTypeId: eventType.id,
@@ -403,9 +346,10 @@ const BookingPage = ({
language: i18n.language,
rescheduleUid,
user: router.query.user,
location: getLocationValue(
booking.locationType ? booking : { ...booking, locationType: selectedLocation }
),
location: getEventLocationValue(locations, {
type: booking.locationType ? booking.locationType : selectedLocationType || "",
phone: booking.phone,
}),
metadata,
customInputs: Object.keys(booking.customInputs || {}).map((inputId) => ({
label: eventType.customInputs.find((input) => input.id === parseInt(inputId))?.label || "",
@@ -414,13 +358,13 @@ const BookingPage = ({
hasHashedBookingLink,
hashedLink,
smsReminderNumber:
selectedLocation === LocationType.Phone ? booking.phone : booking.smsReminderNumber,
selectedLocationType === LocationType.Phone ? booking.phone : booking.smsReminderNumber,
ethSignature: gateState.rainbowToken,
}));
recurringMutation.mutate(recurringBookings);
} else {
mutation.mutate({
...booking,
web3Details,
start: dayjs(date).format(),
end: dayjs(date).add(eventType.length, "minute").format(),
eventTypeId: eventType.id,
@@ -430,9 +374,10 @@ const BookingPage = ({
rescheduleUid,
bookingUid: router.query.bookingUid as string,
user: router.query.user,
location: getLocationValue(
booking.locationType ? booking : { ...booking, locationType: selectedLocation }
),
location: getEventLocationValue(locations, {
type: (booking.locationType ? booking.locationType : selectedLocationType) || "",
phone: booking.phone,
}),
metadata,
customInputs: Object.keys(booking.customInputs || {}).map((inputId) => ({
label: eventType.customInputs.find((input) => input.id === parseInt(inputId))?.label || "",
@@ -441,16 +386,18 @@ const BookingPage = ({
hasHashedBookingLink,
hashedLink,
smsReminderNumber:
selectedLocation === LocationType.Phone ? booking.phone : booking.smsReminderNumber,
selectedLocationType === LocationType.Phone ? booking.phone : booking.smsReminderNumber,
ethSignature: gateState.rainbowToken,
});
}
};
// Should be disabled when rescheduleUid is present and data was found in defaultUserValues name/email fields.
const disableInput = !!rescheduleUid && !!defaultUserValues.email && !!defaultUserValues.name;
const disableLocations = !!rescheduleUid;
const disabledExceptForOwner = disableInput && !loggedInIsOwner;
const inputClassName =
"focus:border-brand block w-full rounded-sm border-gray-300 focus:ring-black disabled:bg-gray-200 disabled:hover:cursor-not-allowed dark:border-gray-900 dark:bg-gray-700 dark:text-white dark:selection:bg-green-500 disabled:dark:text-gray-500 text-sm";
"dark:placeholder:text-darkgray-600 focus:border-brand dark:border-darkgray-300 dark:text-darkgray-900 block w-full rounded-md border-gray-300 text-sm focus:ring-black disabled:bg-gray-200 disabled:hover:cursor-not-allowed dark:bg-transparent dark:selection:bg-green-500 disabled:dark:text-gray-500";
let isSmsReminderNumberNeeded = false;
@@ -467,8 +414,16 @@ const BookingPage = ({
});
}
// Define conditional gates here
const gates = [
// Rainbow gate is only added if the event has both a `blockchainId` and a `smartContractAddress`
eventType.metadata && eventType.metadata.blockchainId && eventType.metadata.smartContractAddress
? ("rainbow" as Gate)
: undefined,
];
return (
<div>
<Gates gates={gates} metadata={eventType.metadata} dispatch={gateDispatcher}>
<Head>
<title>
{rescheduleUid
@@ -495,116 +450,121 @@ const BookingPage = ({
className={classNames(
"main overflow-hidden",
isEmbed ? "" : "border border-gray-200",
isBackgroundTransparent ? "" : "dark:border-1 bg-white dark:bg-gray-800",
"rounded-md dark:border-gray-600 sm:border"
isBackgroundTransparent ? "" : "dark:border-1 dark:bg-darkgray-100 bg-white",
"dark:border-darkgray-300 rounded-md sm:border"
)}>
<div className="sm:flex">
<div className="px-6 pt-6 pb-0 sm:w-1/2 sm:border-r sm:pb-6 sm:dark:border-gray-700">
<div className="sm:dark:border-darkgray-300 dark:text-darkgray-600 flex flex-col px-6 pt-6 pb-0 text-gray-600 sm:w-1/2 sm:border-r sm:pb-6">
<UserAvatars
profile={profile}
users={eventType.users}
showMembers={eventType.schedulingType !== SchedulingType.ROUND_ROBIN}
size={14}
size={10}
truncateAfter={3}
/>
<h2 className="font-cal text-bookinglight mt-2 font-medium dark:text-gray-300">
<h2 className="mt-2 break-words text-sm font-medium text-gray-500 dark:text-gray-300">
{profile.name}
</h2>
<h1 className="text-bookingdark mb-4 text-xl font-semibold dark:text-white">
<h1 className="font-cal dark:text-darkgray-900 break-words text-2xl text-gray-900 ">
{eventType.title}
</h1>
{!!eventType.seatsPerTimeSlot && (
<p
className={`${
booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5
? "text-rose-600"
: booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.33
? "text-yellow-500"
: "text-emerald-400"
} mb-2`}>
{booking
? eventType.seatsPerTimeSlot - booking.attendees.length
: eventType.seatsPerTimeSlot}{" "}
/ {eventType.seatsPerTimeSlot} {t("seats_available")}
</p>
)}
{eventType?.description && (
<p className="text-bookinglight mb-2 text-sm dark:text-white">
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
{eventType.description}
</p>
)}
{eventType?.requiresConfirmation && (
<p className="text-bookinglight mb-2 text-sm dark:text-white">
<Icon.FiClipboard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
{t("requires_confirmation")}
</p>
)}
<p className="text-bookinglight mb-2 text-sm dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-400" />
{eventType.length} {t("minutes")}
</p>
{eventType.price > 0 && (
<p className="text-bookinglight mb-1 -ml-2 px-2 py-1 text-sm dark:text-white">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
style="currency"
currency={eventType.currency.toUpperCase()}
/>
</IntlProvider>
</p>
)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
<div className="mb-3 text-sm text-gray-600 dark:text-white">
<Icon.FiRefreshCw className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-400" />
<p className="mb-1 -ml-2 inline px-2 py-1">
{getEveryFreqFor({
t,
recurringEvent: eventType.recurringEvent,
recurringCount: recurringEventCount,
})}
</p>
</div>
)}
<div className="text-bookinghighlight mb-4 flex items-center text-sm">
<Icon.FiCalendar className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
<div>
{(rescheduleUid || !eventType.recurringEvent?.freq) &&
parseDate(dayjs(date).tz(timeZone()), i18n)}
{!rescheduleUid &&
eventType.recurringEvent?.freq &&
recurringStrings.slice(0, 5).map((aDate, key) => <p key={key}>{aDate}</p>)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringStrings.length > 5 && (
<div className="flex">
<Tooltip
content={recurringStrings.slice(5).map((aDate, key) => (
<p key={key}>{aDate}</p>
))}>
<p className="text-sm text-gray-600 dark:text-white">
{t("plus_more", { count: recurringStrings.length - 5 })}
</p>
</Tooltip>
<div className="mt-4 flex flex-col space-y-3 lg:mt-9">
{eventType?.description && (
<div className="dark:text-darkgray-600 flex text-sm font-medium text-gray-600">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
</div>
)}
</div>
</div>
{eventTypeDetail.isWeb3Active && eventType.metadata.smartContractAddress && (
<p className="text-bookinglight mb-1 -ml-2 px-2 py-1">
{t("requires_ownership_of_a_token") + " " + eventType.metadata.smartContractAddress}
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<div className="dark:text-darkgray-600 flex items-center text-sm font-medium text-gray-600">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
</div>
{t("requires_confirmation")}
</div>
)}
<p className="dark:text-darkgray-600 text-sm font-medium text-gray-600">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
)}
{booking?.startTime && rescheduleUid && (
<div>
<p className="mt-8 mb-2 text-sm text-gray-600 dark:text-white" data-testid="former_time_p">
{t("former_time")}
</p>
<p className="text-gray-500 line-through dark:text-white">
<Icon.FiCalendar className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
{eventType.price > 0 && (
<p className="text-bookinglight -ml-2 px-2 text-sm ">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
style="currency"
currency={eventType.currency.toUpperCase()}
/>
</IntlProvider>
</p>
)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
<div className="items-start text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiRefreshCw className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
<p className="-ml-2 inline-block items-center px-2">
{getEveryFreqFor({
t,
recurringEvent: eventType.recurringEvent,
recurringCount: recurringEventCount,
})}
</p>
</div>
)}
<div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiCalendar className="mr-[10px] ml-[2px] mt-[2px] inline-block h-4 w-4" />
<div className="text-sm font-medium">
{(rescheduleUid || !eventType.recurringEvent?.freq) &&
parseDate(dayjs(date).tz(timeZone()), i18n)}
{!rescheduleUid &&
eventType.recurringEvent?.freq &&
recurringStrings.slice(0, 5).map((aDate, key) => <p key={key}>{aDate}</p>)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringStrings.length > 5 && (
<div className="flex">
<Tooltip
content={recurringStrings.slice(5).map((aDate, key) => (
<p key={key}>{aDate}</p>
))}>
<p className="dark:text-darkgray-600 text-sm">
{t("plus_more", { count: recurringStrings.length - 5 })}
</p>
</Tooltip>
</div>
)}
</div>
</div>
)}
{booking?.startTime && rescheduleUid && (
<div>
<p className="mt-8 mb-2 text-sm " data-testid="former_time_p">
{t("former_time")}
</p>
<p className="line-through ">
<Icon.FiCalendar className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
</p>
</div>
)}
{!!eventType.seatsPerTimeSlot && (
<div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiUser className="mr-[10px] ml-[2px] mt-[2px] inline-block h-4 w-4" />
<p
className={`${
booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5
? "text-rose-600"
: booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.33
? "text-yellow-500"
: "text-bookinghighlight"
} mb-2 font-medium`}>
{booking
? eventType.seatsPerTimeSlot - booking.attendees.length
: eventType.seatsPerTimeSlot}{" "}
/ {eventType.seatsPerTimeSlot} {t("seats_available")}
</p>
</div>
)}
</div>
</div>
<div className="p-6 sm:w-1/2">
<Form form={bookingForm} handleSubmit={bookEvent}>
@@ -656,23 +616,34 @@ const BookingPage = ({
<span className="block text-sm font-medium text-gray-700 dark:text-white">
{t("location")}
</span>
{locations.map((location, i) => (
<label key={i} className="block">
<input
type="radio"
className="location h-4 w-4 border-gray-300 text-black focus:ring-black ltr:mr-2 rtl:ml-2"
{...bookingForm.register("locationType", { required: true })}
value={location.type}
defaultChecked={selectedLocation === location.type}
/>
<span className="text-sm ltr:ml-2 rtl:mr-2 dark:text-gray-500">
{locationLabels[location.type]}
</span>
</label>
))}
{locations.map((location, i) => {
const locationString = locationKeyToString(location);
// TODO: Right now selectedLocationType isn't send by getSSP. Once that's available defaultChecked should work and show the location in the original booking
const defaultChecked = rescheduleUid ? selectedLocationType === location.type : i === 0;
if (typeof locationString !== "string") {
// It's possible that location app got uninstalled
return null;
}
return (
<label key={i} className="block">
<input
type="radio"
disabled={!!disableLocations}
className="location dark:bg-darkgray-300 dark:border-darkgray-300 h-4 w-4 border-gray-300 text-black focus:ring-black ltr:mr-2 rtl:ml-2"
{...bookingForm.register("locationType", { required: true })}
value={location.type}
defaultChecked={defaultChecked}
/>
<span className="text-sm ltr:ml-2 rtl:mr-2 dark:text-white">
{locationKeyToString(location)}
</span>
</label>
);
})}
</div>
)}
{selectedLocation === LocationType.Phone && (
{/* TODO: Change name and id ="phone" to something generic */}
{AttendeeInput && (
<div className="mb-4">
<label
htmlFor="phone"
@@ -680,10 +651,10 @@ const BookingPage = ({
{t("phone_number")}
</label>
<div className="mt-1">
<PhoneInput<BookingFormValues>
<AttendeeInput<BookingFormValues>
control={bookingForm.control}
name="phone"
placeholder={t("enter_phone_number")}
placeholder={t(selectedLocation?.attendeeInputPlaceholder || "")}
id="phone"
required
disabled={disableInput}
@@ -713,6 +684,7 @@ const BookingPage = ({
{...bookingForm.register(`customInputs.${input.id}`, {
required: input.required,
})}
required={input.required}
id={"custom_" + input.id}
rows={3}
className={inputClassName}
@@ -726,6 +698,7 @@ const BookingPage = ({
{...bookingForm.register(`customInputs.${input.id}`, {
required: input.required,
})}
required={input.required}
id={"custom_" + input.id}
className={inputClassName}
placeholder={input.placeholder}
@@ -738,6 +711,7 @@ const BookingPage = ({
{...bookingForm.register(`customInputs.${input.id}`, {
required: input.required,
})}
required={input.required}
id={"custom_" + input.id}
className={inputClassName}
placeholder=""
@@ -751,6 +725,7 @@ const BookingPage = ({
{...bookingForm.register(`customInputs.${input.id}`, {
required: input.required,
})}
required={input.required}
id={"custom_" + input.id}
className="h-4 w-4 rounded border-gray-300 text-black focus:ring-black disabled:bg-gray-200 ltr:mr-2 rtl:ml-2 disabled:dark:text-gray-500"
placeholder=""
@@ -830,7 +805,7 @@ const BookingPage = ({
)}
</div>
)}
{isSmsReminderNumberNeeded && selectedLocation !== LocationType.Phone && (
{isSmsReminderNumberNeeded && selectedLocationType !== LocationType.Phone && (
<div className="mb-4">
<label
htmlFor="smsReminderNumber"
@@ -844,7 +819,6 @@ const BookingPage = ({
placeholder={t("enter_phone_number")}
id="smsReminderNumber"
required
disabled={disableInput}
/>
</div>
{bookingForm.formState.errors.smsReminderNumber && (
@@ -883,16 +857,22 @@ const BookingPage = ({
)}
</div>
<div className="flex items-start space-x-2 rtl:space-x-reverse">
<div className="flex justify-end space-x-2 rtl:space-x-reverse">
<Button
color="secondary"
type="button"
onClick={() => router.back()}
// We override this for this component only for now - as we don't support darkmode everywhere in the app
className="dark:border-none">
{t("cancel")}
</Button>
<Button
type="submit"
className="dark:bg-darkmodebrand dark:text-darkmodebrandcontrast rounded-md"
data-testid={rescheduleUid ? "confirm-reschedule-button" : "confirm-book-button"}
loading={mutation.isLoading || recurringMutation.isLoading}>
{rescheduleUid ? t("reschedule") : t("confirm")}
</Button>
<Button color="secondary" type="button" onClick={() => router.back()}>
{t("cancel")}
</Button>
</div>
</Form>
{(mutation.isError || recurringMutation.isError) && (
@@ -902,7 +882,7 @@ const BookingPage = ({
</div>
</div>
</main>
</div>
</Gates>
);
};
+127 -350
View File
@@ -1,11 +1,18 @@
import { ErrorMessage } from "@hookform/error-message";
import { zodResolver } from "@hookform/resolvers/zod";
import { isValidPhoneNumber } from "libphonenumber-js";
import { useEffect } from "react";
import { Controller, useForm, useWatch } from "react-hook-form";
import { z } from "zod";
import { LocationOptionsToString } from "@calcom/app-store/locations";
import { LocationType } from "@calcom/core/location";
import {
LocationType,
getEventLocationType,
EventLocationType,
LocationObject,
} from "@calcom/app-store/locations";
import { getMessageForOrganizer } from "@calcom/app-store/locations";
import { getHumanReadableLocationValue } from "@calcom/app-store/locations";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
import { Button } from "@calcom/ui";
@@ -15,7 +22,6 @@ import PhoneInput from "@calcom/ui/form/PhoneInputLazy";
import { Form } from "@calcom/ui/form/fields";
import { QueryCell } from "@lib/QueryCell";
import { linkValueToString } from "@lib/linkValueToString";
import CheckboxField from "@components/ui/form/CheckboxField";
import Select from "@components/ui/form/Select";
@@ -24,33 +30,46 @@ type BookingItem = inferQueryOutput<"viewer.bookings">["bookings"][number];
type OptionTypeBase = {
label: string;
value: LocationType;
value: EventLocationType["type"];
disabled?: boolean;
};
type LocationFormValues = {
locationType: LocationType;
locationAddress?: string;
locationLink?: string;
locationPhoneNumber?: string;
displayLocationPublicly?: boolean;
};
interface ISetLocationDialog {
saveLocation: (newLocationType: LocationType, details: { [key: string]: string }) => void;
saveLocation: (newLocationType: EventLocationType["type"], details: { [key: string]: string }) => void;
selection?: OptionTypeBase;
booking?: BookingItem;
defaultValues?: {
type: LocationType;
address?: string | undefined;
link?: string | undefined;
hostPhoneNumber?: string | undefined;
displayLocationPublicly?: boolean | undefined;
}[];
defaultValues?: LocationObject[];
setShowLocationModal: React.Dispatch<React.SetStateAction<boolean>>;
isOpenDialog: boolean;
setSelectedLocation?: (param: OptionTypeBase | undefined) => void;
}
const LocationInput = (props: {
eventLocationType: EventLocationType;
locationFormMethods: ReturnType<typeof useForm>;
id: string;
required: boolean;
placeholder: string;
className?: string;
defaultValue?: string;
}): JSX.Element | null => {
const { eventLocationType, locationFormMethods, ...remainingProps } = props;
if (eventLocationType?.organizerInputType === "text") {
return (
<input {...locationFormMethods.register(eventLocationType.variable)} type="text" {...remainingProps} />
);
} else if (eventLocationType?.organizerInputType === "phone") {
return (
<PhoneInput
name={eventLocationType.variable}
control={locationFormMethods.control}
{...remainingProps}
/>
);
}
return null;
};
export const EditLocationDialog = (props: ISetLocationDialog) => {
const {
saveLocation,
@@ -73,37 +92,52 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
const locationFormSchema = z.object({
locationType: z.string(),
phone: z.string().optional().nullable(),
locationAddress: z.string().optional(),
locationLink:
selection?.value === LocationType.Whereby
? z
.string()
.regex(/^http(s)?:\/\/(www\.)?whereby.com\/[a-zA-Z0-9]*/)
.optional()
: selection?.value === LocationType.Around
? z
.string()
.regex(/^http(s)?:\/\/(www\.)?around.co\/[a-zA-Z0-9]*/)
.optional()
: selection?.value === LocationType.Ping
? z
.string()
.regex(/^http(s)?:\/\/(www\.)?ping.gg\/call\/[a-zA-Z0-9]*/)
.optional()
: selection?.value === LocationType.Riverside
? z
.string()
.regex(/^http(s)?:\/\/(www\.)?riverside.fm\/studio\/[a-zA-Z0-9]*/)
.optional()
: z.string().url().optional(),
locationLink: z
.string()
.optional()
.superRefine((val, ctx) => {
if (
eventLocationType &&
!eventLocationType.default &&
eventLocationType.linkType === "static" &&
eventLocationType.urlRegExp
) {
const valid = z.string().regex(new RegExp(eventLocationType.urlRegExp)).safeParse(val).success;
if (!valid) {
const sampleUrl = eventLocationType.organizerInputPlaceholder;
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Invalid URL for ${eventLocationType.label}. ${
sampleUrl ? "Sample URL: " + sampleUrl : ""
}`,
});
}
return;
}
const valid = z.string().url().optional().safeParse(val).success;
if (!valid) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Invalid URL`,
});
}
return;
}),
displayLocationPublicly: z.boolean().optional(),
locationPhoneNumber: z
.string()
.refine((val) => isValidPhoneNumber(val))
.nullable()
.refine((val) => {
if (val === null) return false;
return isValidPhoneNumber(val);
})
.optional(),
});
const locationFormMethods = useForm<LocationFormValues>({
const locationFormMethods = useForm({
mode: "onSubmit",
resolver: zodResolver(locationFormSchema),
});
@@ -113,28 +147,43 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
name: "locationType",
});
const LocationOptions =
selectedLocation === LocationType.InPerson ? (
<>
const eventLocationType = getEventLocationType(selectedLocation);
const defaultLocation = defaultValues?.find(
(location: { type: EventLocationType["type"] }) => location.type === eventLocationType?.type
);
const LocationOptions = (() => {
if (eventLocationType && eventLocationType.organizerInputType && LocationInput) {
if (!eventLocationType.variable) {
console.error("eventLocationType.variable can't be undefined");
return null;
}
return (
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700">
{t("set_address_place")}
<label htmlFor="locationInput" className="block text-sm font-medium text-gray-700">
{t(eventLocationType.messageForOrganizer || "")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationAddress")}
id="address"
<LocationInput
locationFormMethods={locationFormMethods}
eventLocationType={eventLocationType}
id="locationInput"
placeholder={t(eventLocationType.organizerInputPlaceholder || "")}
required
className="block w-full rounded-sm border-gray-300 text-sm"
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.InPerson
)?.address
: undefined
defaultLocation ? defaultLocation[eventLocationType.defaultValueVariable] : undefined
}
/>
<ErrorMessage
errors={locationFormMethods.formState.errors}
name={eventLocationType.variable}
className="mt-1 text-sm text-red-500"
as="p"
/>
</div>
{!booking && (
<div className="mt-3">
@@ -143,12 +192,7 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.InPerson)
?.displayLocationPublicly
: undefined
}
defaultChecked={defaultLocation?.displayLocationPublicly}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
@@ -160,286 +204,11 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
</div>
)}
</div>
</>
) : selectedLocation === LocationType.Link ? (
<div>
<label htmlFor="link" className="block text-sm font-medium text-gray-700">
{t("set_link_meeting")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationLink")}
required
id="link"
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.Link
)?.link
: undefined
}
/>
{locationFormMethods.formState.errors.locationLink && (
<p className="mt-1 text-sm text-red-500">{t("url_start_with_https")}</p>
)}
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
description={t("display_location_label")}
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.Link)
?.displayLocationPublicly
: undefined
}
onChange={(e) => locationFormMethods.setValue("displayLocationPublicly", e.target.checked)}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
) : selectedLocation === LocationType.UserPhone ? (
<div>
<label htmlFor="phonenumber" className="block text-sm font-medium text-gray-700">
{t("set_your_phone_number")}
{locationFormMethods.formState?.errors?.locationPhoneNumber?.message}
</label>
<div className="mt-1">
<PhoneInput<LocationFormValues>
control={locationFormMethods.control}
name="locationPhoneNumber"
required
id="locationPhoneNumber"
placeholder={t("host_phone_number")}
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.UserPhone
)?.hostPhoneNumber
: undefined
}
/>
{locationFormMethods.formState.errors.locationPhoneNumber && (
<p className="mt-1 text-sm text-red-500">{t("invalid_number")}</p>
)}
</div>
</div>
) : selectedLocation === LocationType.Whereby ? (
<>
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700">
{t("set_whereby_link")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationLink")}
id="wherebylink"
placeholder="https://www.whereby.com/cal"
required
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.Whereby
)?.address
: undefined
}
/>
{locationFormMethods.formState.errors.locationLink && (
<p className="mt-1 text-sm text-red-500">{t("invalid_whereby_link")}</p>
)}
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.Whereby)
?.displayLocationPublicly
: undefined
}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
</>
) : selectedLocation === LocationType.Around ? (
<>
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700">
{t("set_around_link")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationLink")}
id="aroundlink"
placeholder="https://www.around.co/rick"
required
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.Around
)?.address
: undefined
}
/>
{locationFormMethods.formState.errors.locationLink && (
<p className="mt-1 text-sm text-red-500">{t("invalid_around_link")}</p>
)}
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.Around)
?.displayLocationPublicly
: undefined
}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
</>
) : selectedLocation === LocationType.Ping ? (
<>
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700">
{t("set_ping_link")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationLink")}
id="pinglink"
placeholder="https://www.ping.gg/call/theo"
required
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.Ping
)?.address
: undefined
}
/>
{locationFormMethods.formState.errors.locationLink && (
<p className="mt-1 text-sm text-red-500">{t("invalid_ping_link")}</p>
)}
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.Ping)
?.displayLocationPublicly
: undefined
}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
</>
) : selectedLocation === LocationType.Riverside ? (
<>
<div>
<label htmlFor="address" className="block text-sm font-medium text-gray-700">
{t("set_riverside_link")}
</label>
<div className="mt-1">
<input
type="text"
{...locationFormMethods.register("locationLink")}
id="aroundlink"
placeholder="https://www.riverside.fm/studio/rick"
required
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={
defaultValues
? defaultValues.find(
(location: { type: LocationType }) => location.type === LocationType.Riverside
)?.address
: undefined
}
/>
{locationFormMethods.formState.errors.locationLink && (
<p className="mt-1 text-sm text-red-500">{t("invalid_riverside_link")}</p>
)}
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={
defaultValues
? defaultValues.find((location) => location.type === LocationType.Riverside)
?.displayLocationPublicly
: undefined
}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
</>
) : (
<p className="text-sm">{LocationOptionsToString(selectedLocation, t)}</p>
);
);
} else {
return <p className="text-sm">{getMessageForOrganizer(selectedLocation, t)}</p>;
}
})();
return (
<Dialog open={isOpenDialog}>
@@ -462,7 +231,9 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
{booking && (
<>
<p className="mt-6 mb-2 ml-1 text-sm font-bold text-black">{t("current_location")}:</p>
<p className="mb-2 ml-1 text-sm text-black">{linkValueToString(booking.location, t)}</p>
<p className="mb-2 ml-1 text-sm text-black">
{getHumanReadableLocationValue(booking.location, t)}
</p>
</>
)}
<Form
@@ -474,23 +245,29 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
if (newLocation === LocationType.InPerson) {
details = {
address: values.locationAddress,
displayLocationPublicly,
};
}
const eventLocationType = getEventLocationType(newLocation);
// TODO: There can be a property that tells if it is to be saved in `link`
if (
newLocation === LocationType.Link ||
newLocation === LocationType.Whereby ||
newLocation === LocationType.Around ||
newLocation === LocationType.Riverside ||
newLocation === LocationType.Ping
(!eventLocationType?.default && eventLocationType?.linkType === "static")
) {
details = { link: values.locationLink, displayLocationPublicly };
details = { link: values.locationLink };
}
if (newLocation === LocationType.UserPhone) {
details = { hostPhoneNumber: values.locationPhoneNumber };
}
if (eventLocationType?.organizerInputType) {
details = {
...details,
displayLocationPublicly,
};
}
saveLocation(newLocation, details);
setShowLocationModal(false);
setSelectedLocation?.(undefined);
@@ -5,10 +5,10 @@ import { useMutation } from "react-query";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import showToast from "@calcom/lib/notification";
import { trpc } from "@calcom/trpc/react";
import Button from "@calcom/ui/Button";
import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog";
import { Icon } from "@calcom/ui/Icon";
import { TextArea } from "@calcom/ui/form/fields";
import Button from "@calcom/ui/v2/core/Button";
import * as fetchWrapper from "@lib/core/http/fetch-wrapper";
@@ -7,7 +7,6 @@ import { useForm } from "react-hook-form";
import type { z } from "zod";
import classNames from "@calcom/lib/classNames";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import showToast from "@calcom/lib/notification";
import { createEventTypeInput } from "@calcom/prisma/zod/custom/eventtype";
@@ -49,9 +48,8 @@ interface CreateEventTypeBtnProps {
}
export default function CreateEventTypeButton(props: CreateEventTypeBtnProps) {
const { t } = useLocale();
const { t, isLocaleReady } = useLocale();
const router = useRouter();
// URL encoded params
const teamId: number | undefined =
typeof router.query.teamId === "string" && router.query.teamId
@@ -139,7 +137,9 @@ export default function CreateEventTypeButton(props: CreateEventTypeBtnProps) {
{ shallow: true }
);
};
if (!isLocaleReady) {
return null;
}
return (
<Dialog
name="new-eventtype"
@@ -30,7 +30,7 @@ export const EventTypeDescription = ({ eventType, className }: EventTypeDescript
return (
<>
<div className={classNames("text-neutral-500 dark:text-white", className)}>
<div className={classNames("text-gray-600 dark:text-white", className)}>
{eventType.description && (
<h2 className="max-w-[280px] overflow-hidden text-ellipsis opacity-60 sm:max-w-[500px]">
{eventType.description.substring(0, 100)}
@@ -16,6 +16,10 @@ type RecurringEventControllerProps = {
onRecurringEventDefined: (value: boolean) => void;
};
/**
* @deprecated
* use component from `/apps/web/components/v2/eventtype/RecurringEventController` instead
**/
export default function RecurringEventController({
recurringEvent,
formMethods,
@@ -43,8 +47,8 @@ export default function RecurringEventController({
<Alert severity="warning" title={t("warning_payment_recurring_event")} />
) : (
<>
<div className="relative flex items-start">
<div className="flex h-5 items-center">
<div className="flex items-start">
<div className="flex h-5 items-start">
<input
onChange={(event) => {
onRecurringEventDefined(event?.target.checked);
@@ -1,5 +1,3 @@
import React from "react";
import { SkeletonAvatar, SkeletonContainer, SkeletonText } from "@calcom/ui";
import { Icon } from "@calcom/ui/Icon";
@@ -9,11 +7,11 @@ function SkeletonLoader() {
<div className="mb-4 flex items-center">
<SkeletonAvatar width="8" height="8" />
<div className="space-y-1">
<SkeletonText height="4" width="16" />
<SkeletonText height="4" width="24" />
<SkeletonText className="h-4 w-16" />
<SkeletonText className="h-4 w-24" />
</div>
</div>
<ul className="divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
<ul className="divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
@@ -44,19 +42,6 @@ function SkeletonItem() {
</ul>
</div>
</div>
<div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 sm:flex">
<div className="flex justify-between rtl:space-x-reverse">
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
<Icon.FiExternalLink className="h-5 w-5" />
</div>
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
<Icon.FiLink className="h-5 w-5" />
</div>
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
<Icon.FiMoreHorizontal className="h-5 w-5" />
</div>
</div>
</div>
</li>
);
}
@@ -0,0 +1,42 @@
import { InstallAppButtonWithoutPlanCheck } from "@calcom/app-store/components";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { App } from "@calcom/types/App";
import Button from "@calcom/ui/v2/core/Button";
interface ICalendarItem {
title: string;
description?: string;
imageSrc: string;
type: App["type"];
}
const CalendarItem = (props: ICalendarItem) => {
const { title, imageSrc, type } = props;
const { t } = useLocale();
return (
<div className="flex flex-row items-center p-5">
<img src={imageSrc} alt={title} className="h-8 w-8" />
<p className="mx-3 text-sm font-bold">{title}</p>
<InstallAppButtonWithoutPlanCheck
type={type}
render={(buttonProps) => (
<Button
{...buttonProps}
color="secondary"
type="button"
onClick={(event) => {
// Save cookie key to return url step
document.cookie = `return-to=${window.location.href};path=/;max-age=3600`;
buttonProps && buttonProps.onClick && buttonProps?.onClick(event);
}}
className="ml-auto rounded-md border border-gray-200 py-[10px] px-4 text-sm font-bold">
{t("connect")}
</Button>
)}
/>
</div>
);
};
export { CalendarItem };
@@ -0,0 +1,86 @@
import { useMutation } from "react-query";
import showToast from "@calcom/lib/notification";
import { trpc } from "@calcom/trpc/react";
import { Switch } from "@calcom/ui/v2";
import classNames from "@lib/classNames";
interface ICalendarSwitchProps {
title: string;
externalId: string;
type: string;
isChecked: boolean;
name: string;
isLastItemInList?: boolean;
}
const CalendarSwitch = (props: ICalendarSwitchProps) => {
const { title, externalId, type, isChecked, name, isLastItemInList = false } = props;
const utils = trpc.useContext();
const mutation = useMutation<
unknown,
unknown,
{
isOn: boolean;
}
>(
async ({ isOn }: { isOn: boolean }) => {
const body = {
integration: type,
externalId: externalId,
};
if (isOn) {
const res = await fetch("/api/availability/calendar", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!res.ok) {
throw new Error("Something went wrong");
}
} else {
const res = await fetch("/api/availability/calendar", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!res.ok) {
throw new Error("Something went wrong");
}
}
},
{
async onSettled() {
await utils.invalidateQueries(["viewer.integrations"]);
},
onError() {
showToast(`Something went wrong when toggling "${title}""`, "error");
},
}
);
return (
<div className={classNames("flex flex-row items-center", !isLastItemInList ? "mb-4" : "")}>
<div className="flex pl-2">
<Switch
id={externalId}
defaultChecked={isChecked}
onCheckedChange={(isOn: boolean) => {
mutation.mutate({ isOn });
}}
/>
</div>
<label className="ml-3 text-sm font-medium leading-5" htmlFor={externalId}>
{name}
</label>
</div>
);
};
export { CalendarSwitch };
@@ -0,0 +1,75 @@
import { DotsHorizontalIcon } from "@heroicons/react/solid";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button } from "@calcom/ui/v2";
import { CalendarSwitch } from "./CalendarSwitch";
interface IConnectedCalendarItem {
name: string;
logo: string;
externalId?: string;
integrationType: string;
calendars?: {
primary: true | null;
isSelected: boolean;
credentialId: number;
name?: string | undefined;
readOnly?: boolean | undefined;
userId?: number | undefined;
integration?: string | undefined;
externalId: string;
}[];
}
const ConnectedCalendarItem = (prop: IConnectedCalendarItem) => {
const { name, logo, externalId, calendars, integrationType } = prop;
const { t } = useLocale();
return (
<>
<div className="flex flex-row items-center p-4">
<img src={logo} alt={name} className="m-1 h-8 w-8" />
<div className="mx-4">
<p className="font-sans text-sm font-bold leading-5">
{name}{" "}
<span className="mx-1 rounded-[4px] bg-green-100 py-[2px] px-[6px] font-sans text-xs font-medium text-green-600">
{t("default")}
</span>
</p>
<div className="fle-row flex">
<span
title={externalId}
className="max-w-44 mt-1 overflow-hidden text-ellipsis whitespace-nowrap font-sans text-sm text-gray-500">
{externalId}{" "}
</span>
</div>
</div>
<Button
color="minimal"
type="button"
className="ml-auto flex rounded-md border border-gray-200 py-[10x] px-4 font-sans text-sm">
{t("edit")}
</Button>
</div>
<div className="h-[1px] w-full border-b border-gray-200" />
<div>
<ul className="p-4">
{calendars?.map((calendar, i) => (
<CalendarSwitch
key={calendar.externalId}
externalId={calendar.externalId}
title={calendar.name || "Nameless Calendar"}
name={calendar.name || "Nameless Calendar"}
type={integrationType}
isChecked={calendar.isSelected}
isLastItemInList={i === calendars.length - 1}
/>
))}
</ul>
</div>
</>
);
};
export { ConnectedCalendarItem };
@@ -0,0 +1,37 @@
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { inferMutationInput, trpc } from "@calcom/trpc/react";
import DestinationCalendarSelector from "@components/DestinationCalendarSelector";
interface ICreateEventsOnCalendarSelectProps {
calendar?: inferMutationInput<"viewer.setDestinationCalendar"> | null;
}
const CreateEventsOnCalendarSelect = (props: ICreateEventsOnCalendarSelectProps) => {
const { calendar } = props;
const { t } = useLocale();
const mutation = trpc.useMutation(["viewer.setDestinationCalendar"]);
return (
<>
<div className="mt-6 flex flex-row">
<div className="w-full">
<label htmlFor="createEventsOn" className="flex text-sm font-medium text-neutral-700">
{t("create_events_on")}
</label>
<div className="mt-2">
<DestinationCalendarSelector
value={calendar ? calendar.externalId : undefined}
onChange={(calendar) => {
mutation.mutate(calendar);
}}
hidePlaceholder
/>
</div>
</div>
</div>
</>
);
};
export { CreateEventsOnCalendarSelect };
@@ -0,0 +1,9 @@
const StepCard: React.FC<{ children: React.ReactNode }> = (props) => {
return (
<div className="mt-10 rounded-md border border-gray-200 bg-white p-4 dark:bg-black sm:p-8">
{props.children}
</div>
);
};
export { StepCard };
@@ -0,0 +1,37 @@
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
interface ISteps {
maxSteps: number;
currentStep: number;
navigateToStep: (step: number) => void;
}
const Steps = (props: ISteps) => {
const { maxSteps, currentStep, navigateToStep } = props;
const { t } = useLocale();
return (
<div className="mt-6 space-y-2">
<p className="text-xs font-medium text-gray-500 dark:text-white">
{t("current_step_of_total", { currentStep: currentStep + 1, maxSteps })}
</p>
<div className="flex w-full space-x-2 rtl:space-x-reverse">
{new Array(maxSteps).fill(0).map((_s, index) => {
return index <= currentStep ? (
<div
key={`step-${index}`}
onClick={() => navigateToStep(index)}
className={classNames(
"h-1 w-1/4 rounded-[1px] bg-black dark:bg-white",
index < currentStep ? "cursor-pointer" : ""
)}
/>
) : (
<div key={`step-${index}`} className="h-1 w-1/4 rounded-[1px] bg-black bg-opacity-25" />
);
})}
</div>
</div>
);
};
export { Steps };
@@ -0,0 +1,107 @@
import { ArrowRightIcon } from "@heroicons/react/solid";
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { List } from "@calcom/ui/List";
import { SkeletonAvatar, SkeletonText, SkeletonButton } from "@calcom/ui/v2";
import { CalendarItem } from "../components/CalendarItem";
import { ConnectedCalendarItem } from "../components/ConnectedCalendarItem";
import { CreateEventsOnCalendarSelect } from "../components/CreateEventsOnCalendarSelect";
interface IConnectCalendarsProps {
nextStep: () => void;
}
const ConnectedCalendars = (props: IConnectCalendarsProps) => {
const { nextStep } = props;
const queryConnectedCalendars = trpc.useQuery(["viewer.connectedCalendars"]);
const { t } = useLocale();
const queryIntegrations = trpc.useQuery([
"viewer.integrations",
{ variant: "calendar", onlyInstalled: false },
]);
const firstCalendar = queryConnectedCalendars.data?.connectedCalendars.find(
(item) => item.calendars && item.calendars?.length > 0
);
const disabledNextButton = firstCalendar === undefined;
const destinationCalendar = queryConnectedCalendars.data?.destinationCalendar;
return (
<>
{/* Already connected calendars */}
{firstCalendar &&
firstCalendar.integration &&
firstCalendar.integration.title &&
firstCalendar.integration.imageSrc && (
<>
<List className="rounded-md border border-gray-200 bg-white p-0 dark:bg-black">
<ConnectedCalendarItem
key={firstCalendar.integration.title}
name={firstCalendar.integration.title}
logo={firstCalendar.integration.imageSrc}
externalId={
firstCalendar && firstCalendar.calendars && firstCalendar.calendars.length > 0
? firstCalendar.calendars[0].externalId
: ""
}
calendars={firstCalendar.calendars}
integrationType={firstCalendar.integration.type}
/>
</List>
{/* Create event on selected calendar */}
<CreateEventsOnCalendarSelect calendar={destinationCalendar} />
<p className="mt-7 text-sm text-gray-500">{t("connect_calendars_from_app_store")}</p>
</>
)}
{/* Connect calendars list */}
{firstCalendar === undefined && queryIntegrations.data && queryIntegrations.data.items.length > 0 && (
<List className="mx-1 divide-y divide-gray-200 rounded-md border border-gray-200 bg-white p-0 dark:bg-black sm:mx-0">
{queryIntegrations.data &&
queryIntegrations.data.items.map((item) => (
<li key={item.title}>
{item.title && item.imageSrc && (
<CalendarItem
type={item.type}
title={item.title}
description={item.description}
imageSrc={item.imageSrc}
/>
)}
</li>
))}
</List>
)}
{queryConnectedCalendars.isLoading && (
<ul className="divide-y divide-gray-200 rounded-md border border-gray-200 bg-white p-0 dark:bg-black">
{[0, 0, 0, 0].map((_item, index) => {
return (
<li className="flex w-full flex-row justify-center border-b-0 py-6" key={index}>
<SkeletonAvatar className="mx-6 h-8 w-8 px-4" />
<SkeletonText className="ml-1 mr-4 mt-3 h-5 w-full" />
<SkeletonButton className="mr-6 h-8 w-20 rounded-md p-5" />
</li>
);
})}
</ul>
)}
<button
type="button"
data-testid="save-calendar-button"
className={classNames(
"mt-8 flex w-full flex-row justify-center rounded-md border border-black bg-black p-2 text-center text-sm text-white",
disabledNextButton ? "cursor-not-allowed opacity-20" : ""
)}
onClick={() => nextStep()}
disabled={disabledNextButton}>
{firstCalendar ? `${t("continue")}` : `${t("next_step_text")}`}
<ArrowRightIcon className="ml-2 h-4 w-4 self-center" aria-hidden="true" />
</button>
</>
);
};
export { ConnectedCalendars };
@@ -0,0 +1,93 @@
import { ArrowRightIcon } from "@heroicons/react/solid";
import { useRouter } from "next/router";
import { useForm } from "react-hook-form";
import { Schedule } from "@calcom/features/schedules";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc, TRPCClientErrorLike } from "@calcom/trpc/react";
import { AppRouter } from "@calcom/trpc/server/routers/_app";
import { Form } from "@calcom/ui/form/fields";
import { Button } from "@calcom/ui/v2";
import { DEFAULT_SCHEDULE } from "@lib/availability";
import type { Schedule as ScheduleType } from "@lib/types/schedule";
interface ISetupAvailabilityProps {
nextStep: () => void;
defaultScheduleId?: number | null;
defaultAvailability?: { schedule?: TimeRanges[][] };
}
interface ScheduleFormValues {
schedule: ScheduleType;
}
const SetupAvailability = (props: ISetupAvailabilityProps) => {
const { defaultScheduleId } = props;
const { t } = useLocale();
const { nextStep } = props;
const router = useRouter();
let queryAvailability;
if (defaultScheduleId) {
queryAvailability = trpc.useQuery(["viewer.availability.schedule", { scheduleId: defaultScheduleId }], {
enabled: router.isReady,
});
}
const availabilityForm = useForm({
defaultValues: { schedule: queryAvailability?.data?.availability || DEFAULT_SCHEDULE },
});
const mutationOptions = {
onError: (error: TRPCClientErrorLike<AppRouter>) => {
throw new Error(error.message);
},
onSuccess: () => {
nextStep();
},
};
const createSchedule = trpc.useMutation("viewer.availability.schedule.create", mutationOptions);
const updateSchedule = trpc.useMutation("viewer.availability.schedule.update", mutationOptions);
return (
<Form<ScheduleFormValues>
className="w-full bg-white text-black dark:bg-opacity-5 dark:text-white"
form={availabilityForm}
handleSubmit={async (values) => {
try {
if (defaultScheduleId) {
await updateSchedule.mutate({
scheduleId: defaultScheduleId,
name: t("default_schedule_name"),
...values,
});
} else {
await createSchedule.mutate({
name: t("default_schedule_name"),
...values,
});
}
} catch (error) {
if (error instanceof Error) {
// setError(error);
// @TODO: log error
}
}
}}>
<Schedule />
<div>
<Button
data-testid="save-availability"
type="submit"
className="mt-2 w-full justify-center p-2 text-sm sm:mt-8"
disabled={availabilityForm.formState.isSubmitting}>
{t("next_step_text")} <ArrowRightIcon className="ml-2 h-4 w-4 self-center" />
</Button>
</div>
</Form>
);
};
export { SetupAvailability };
@@ -0,0 +1,170 @@
import { ArrowRightIcon } from "@heroicons/react/solid";
import { useRouter } from "next/router";
import { FormEvent, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { User } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
import { Button, showToast, TextArea } from "@calcom/ui/v2";
import ImageUploader from "@calcom/ui/v2/core/ImageUploader";
import { AvatarSSR } from "@components/ui/AvatarSSR";
interface IUserProfile {
user?: User;
}
type FormData = {
bio: string;
};
const UserProfile = (props: IUserProfile) => {
const { user } = props;
const { t } = useLocale();
const avatarRef = useRef<HTMLInputElement>(null!);
const bioRef = useRef<HTMLTextAreaElement>(null);
const {
register,
setValue,
handleSubmit,
formState: { errors },
} = useForm<FormData>({ defaultValues: { bio: user?.bio || "" } });
const { data: eventTypes } = trpc.useQuery(["viewer.eventTypes.list"]);
const [imageSrc, setImageSrc] = useState<string>(user?.avatar || "");
const utils = trpc.useContext();
const router = useRouter();
const createEventType = trpc.useMutation("viewer.eventTypes.create");
const mutation = trpc.useMutation("viewer.updateProfile", {
onSuccess: async (_data, context) => {
if (context.avatar) {
showToast(t("your_user_profile_updated_successfully"), "success");
await utils.refetchQueries(["viewer.me"]);
} else {
try {
if (eventTypes?.length === 0) {
await Promise.all(
DEFAULT_EVENT_TYPES.map(async (event) => {
return createEventType.mutate(event);
})
);
}
} catch (error) {
console.error(error);
}
await utils.refetchQueries(["viewer.me"]);
router.push("/");
}
},
onError: () => {
showToast(t("problem_saving_user_profile"), "error");
},
});
const onSubmit = handleSubmit((data: { bio: string }) => {
const { bio } = data;
mutation.mutate({
bio,
completedOnboarding: true,
});
});
async function updateProfileHandler(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const enteredAvatar = avatarRef.current.value;
mutation.mutate({
avatar: enteredAvatar,
});
}
const DEFAULT_EVENT_TYPES = [
{
title: t("15min_meeting"),
slug: "15min",
length: 15,
},
{
title: t("30min_meeting"),
slug: "30min",
length: 30,
},
{
title: t("secret_meeting"),
slug: "secret",
length: 15,
hidden: true,
},
];
return (
<form onSubmit={onSubmit}>
<p className="font-cal text-sm">{t("profile_picture")}</p>
<div className="mt-4 flex flex-row items-center justify-start rtl:justify-end">
{user && <AvatarSSR user={user} alt="Profile picture" className="h-16 w-16" />}
<input
ref={avatarRef}
type="hidden"
name="avatar"
id="avatar"
placeholder="URL"
className="mt-1 block w-full rounded-sm border border-gray-300 px-3 py-2 text-sm focus:border-neutral-800 focus:outline-none focus:ring-neutral-800"
defaultValue={imageSrc}
/>
<div className="flex items-center px-4">
<ImageUploader
target="avatar"
id="avatar-upload"
buttonMsg={t("upload")}
handleAvatarChange={(newAvatar) => {
avatarRef.current.value = newAvatar;
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
"value"
)?.set;
nativeInputValueSetter?.call(avatarRef.current, newAvatar);
const ev2 = new Event("input", { bubbles: true });
avatarRef.current.dispatchEvent(ev2);
updateProfileHandler(ev2 as unknown as FormEvent<HTMLFormElement>);
setImageSrc(newAvatar);
}}
imageSrc={imageSrc}
/>
</div>
</div>
<fieldset className="mt-8">
<label htmlFor="bio" className="mb-2 block text-sm font-medium text-gray-700">
{t("about")}
</label>
<TextArea
{...register("bio", { required: true })}
ref={bioRef}
name="bio"
id="bio"
className="mt-1 block h-[60px] w-full rounded-sm border border-gray-300 px-3 py-2 focus:border-neutral-500 focus:outline-none focus:ring-neutral-500 sm:text-sm"
defaultValue={user?.bio || undefined}
onChange={(event) => {
setValue("bio", event.target.value);
}}
/>
{errors.bio && (
<p data-testid="required" className="text-xs italic text-red-500">
{t("required")}
</p>
)}
<p className="mt-2 font-sans text-sm font-normal text-gray-600 dark:text-white">
{t("few_sentences_about_yourself")}
</p>
</fieldset>
<Button
type="submit"
className="mt-8 flex w-full flex-row justify-center rounded-md border border-black bg-black p-2 text-center text-sm text-white">
{t("finish")}
<ArrowRightIcon className="ml-2 h-4 w-4 self-center" aria-hidden="true" />
</Button>
</form>
);
};
export default UserProfile;
@@ -0,0 +1,122 @@
import { ArrowRightIcon } from "@heroicons/react/outline";
import { useRef, useState } from "react";
import { useForm } from "react-hook-form";
import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { User } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
import TimezoneSelect from "@calcom/ui/form/TimezoneSelect";
import { Button } from "@calcom/ui/v2";
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
interface IUserSettingsProps {
user: User;
nextStep: () => void;
}
type FormData = {
name: string;
};
const UserSettings = (props: IUserSettingsProps) => {
const { user, nextStep } = props;
const { t } = useLocale();
const [selectedTimeZone, setSelectedTimeZone] = useState(user.timeZone ?? dayjs.tz.guess());
const { register, handleSubmit, formState } = useForm<FormData>({
defaultValues: {
name: user?.name || undefined,
},
reValidateMode: "onChange",
});
const { errors } = formState;
const defaultOptions = { required: true, maxLength: 255 };
const utils = trpc.useContext();
const onSuccess = async () => {
await utils.invalidateQueries(["viewer.me"]);
nextStep();
};
const mutation = trpc.useMutation("viewer.updateProfile", {
onSuccess: onSuccess,
});
const { data: stripeCustomer } = trpc.useQuery(["viewer.stripeCustomer"]);
const paymentRequired = stripeCustomer?.isPremium ? !stripeCustomer?.paidForPremium : false;
const onSubmit = handleSubmit((data) => {
if (paymentRequired) {
return;
}
mutation.mutate({
name: data.name,
timeZone: selectedTimeZone,
});
});
const [currentUsername, setCurrentUsername] = useState(user.username || undefined);
const [inputUsernameValue, setInputUsernameValue] = useState(currentUsername);
const usernameRef = useRef<HTMLInputElement>(null!);
return (
<form onSubmit={onSubmit}>
<div className="space-y-6">
{/* Username textfield */}
<UsernameAvailability
readonly={true}
currentUsername={currentUsername}
setCurrentUsername={setCurrentUsername}
inputUsernameValue={inputUsernameValue}
usernameRef={usernameRef}
setInputUsernameValue={setInputUsernameValue}
user={user}
/>
{/* Full name textfield */}
<div className="w-full">
<label htmlFor="name" className="mb-2 block text-sm font-medium text-gray-700">
{t("full_name")}
</label>
<input
{...register("name", defaultOptions)}
id="name"
name="name"
type="text"
autoComplete="off"
autoCorrect="off"
className="w-full rounded-md border border-gray-300 text-sm"
/>
{errors.name && (
<p data-testid="required" className="text-xs italic text-red-500">
{t("required")}
</p>
)}
</div>
{/* Timezone select field */}
<div className="w-full">
<label htmlFor="timeZone" className="block text-sm font-medium text-gray-700">
{t("timezone")}
</label>
<TimezoneSelect
id="timeZone"
value={selectedTimeZone}
onChange={({ value }) => setSelectedTimeZone(value)}
className="mt-2 w-full rounded-md text-sm"
/>
<p className="mt-3 flex flex-row font-sans text-xs leading-tight text-gray-500 dark:text-white">
{t("current_time")} {dayjs().tz(selectedTimeZone).format("LT").toString().toLowerCase()}
</p>
</div>
</div>
<Button
type="submit"
className="mt-8 flex w-full flex-row justify-center"
disabled={mutation.isLoading}>
{t("next_step_text")}
<ArrowRightIcon className="ml-2 h-4 w-4 self-center" aria-hidden="true" />
</Button>
</form>
);
};
export { UserSettings };
@@ -1,17 +1,20 @@
import React, { SyntheticEvent, useState } from "react";
import { ErrorCode } from "@calcom/lib/auth";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import showToast from "@calcom/lib/notification";
import Button from "@calcom/ui/Button";
import { ErrorCode } from "@lib/auth";
import { useLocale } from "@lib/hooks/useLocale";
const ChangePasswordSection = () => {
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const { t } = useLocale();
const { t, isLocaleReady } = useLocale();
// hold display until the locale is loaded
if (!isLocaleReady) {
return null;
}
const errorMessages: { [key: string]: string } = {
[ErrorCode.IncorrectPassword]: t("current_incorrect_password"),
@@ -1,10 +1,14 @@
import { SyntheticEvent, useState } from "react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { ErrorCode } from "@calcom/lib/auth";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import Button from "@calcom/ui/Button";
import { Dialog, DialogContent } from "@calcom/ui/Dialog";
import { Form, Label } from "@calcom/ui/form/fields";
import { PasswordField } from "@calcom/ui/v2/core/form/fields";
import { ErrorCode } from "@lib/auth";
import { useLocale } from "@lib/hooks/useLocale";
import TwoFactor from "@components/auth/TwoFactor";
import TwoFactorAuthAPI from "./TwoFactorAuthAPI";
import TwoFactorModalHeader from "./TwoFactorModalHeader";
@@ -16,15 +20,17 @@ interface DisableTwoFactorAuthModalProps {
onDisable: () => void;
}
interface DisableTwoFactorValues {
totpCode: string;
password: string;
}
const DisableTwoFactorAuthModal = ({ onDisable, onCancel }: DisableTwoFactorAuthModalProps) => {
const [password, setPassword] = useState("");
const [isDisabling, setIsDisabling] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const { t } = useLocale();
async function handleDisable(e: SyntheticEvent) {
e.preventDefault();
const form = useForm<DisableTwoFactorValues>();
async function handleDisable({ totpCode, password }: DisableTwoFactorValues) {
if (isDisabling) {
return;
}
@@ -32,7 +38,7 @@ const DisableTwoFactorAuthModal = ({ onDisable, onCancel }: DisableTwoFactorAuth
setErrorMessage(null);
try {
const response = await TwoFactorAuthAPI.disable(password);
const response = await TwoFactorAuthAPI.disable(password, totpCode);
if (response.status === 200) {
onDisable();
return;
@@ -41,6 +47,12 @@ const DisableTwoFactorAuthModal = ({ onDisable, onCancel }: DisableTwoFactorAuth
const body = await response.json();
if (body.error === ErrorCode.IncorrectPassword) {
setErrorMessage(t("incorrect_password"));
}
if (body.error === ErrorCode.SecondFactorRequired) {
setErrorMessage(t("2fa_required"));
}
if (body.error === ErrorCode.IncorrectTwoFactorCode) {
setErrorMessage(t("incorrect_2fa"));
} else {
setErrorMessage(t("something_went_wrong"));
}
@@ -55,41 +67,32 @@ const DisableTwoFactorAuthModal = ({ onDisable, onCancel }: DisableTwoFactorAuth
return (
<Dialog open={true}>
<DialogContent>
<TwoFactorModalHeader title={t("disable_2fa")} description={t("disable_2fa_recommendation")} />
<Form form={form} handleSubmit={handleDisable}>
<TwoFactorModalHeader title={t("disable_2fa")} description={t("disable_2fa_recommendation")} />
<form onSubmit={handleDisable}>
<div className="mb-4">
<label htmlFor="password" className="mt-4 block text-sm font-medium text-gray-700">
{t("password")}
</label>
<div className="mt-1">
<input
type="password"
name="password"
id="password"
required
value={password}
onInput={(e) => setPassword(e.currentTarget.value)}
className="block w-full rounded-sm border-gray-300 text-sm"
/>
</div>
<PasswordField
labelProps={{
className: "block text-sm font-medium text-gray-700",
}}
{...form.register("password")}
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-black focus:outline-none focus:ring-black"
/>
<Label className="mt-4"> {t("2fa_code")}</Label>
<TwoFactor center={false} />
{errorMessage && <p className="mt-1 text-sm text-red-700">{errorMessage}</p>}
</div>
</form>
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={handleDisable}
disabled={password.length === 0 || isDisabling}>
{t("disable")}
</Button>
<Button color="secondary" onClick={onCancel}>
{t("cancel")}
</Button>
</div>
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<Button type="submit" className="ltr:ml-2 rtl:mr-2" disabled={isDisabling}>
{t("disable")}
</Button>
<Button color="secondary" onClick={onCancel}>
{t("cancel")}
</Button>
</div>
</Form>
</DialogContent>
</Dialog>
);
@@ -1,10 +1,13 @@
import React, { SyntheticEvent, useState } from "react";
import React, { BaseSyntheticEvent, useState } from "react";
import { useForm } from "react-hook-form";
import { ErrorCode } from "@calcom/lib/auth";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import Button from "@calcom/ui/Button";
import { Dialog, DialogContent } from "@calcom/ui/Dialog";
import { Form } from "@calcom/ui/v2/core/form/fields";
import { ErrorCode } from "@lib/auth";
import { useLocale } from "@lib/hooks/useLocale";
import TwoFactor from "@components/auth/TwoFactor";
import TwoFactorAuthAPI from "./TwoFactorAuthAPI";
import TwoFactorModalHeader from "./TwoFactorModalHeader";
@@ -39,8 +42,14 @@ const WithStep = ({
return step === current ? children : null;
};
interface EnableTwoFactorValues {
totpCode: string;
}
const EnableTwoFactorModal = ({ onEnable, onCancel }: EnableTwoFactorModalProps) => {
const { t } = useLocale();
const form = useForm<EnableTwoFactorValues>();
const setupDescriptions = {
[SetupStep.ConfirmPassword]: t("2fa_confirm_current_password"),
[SetupStep.DisplayQrCode]: t("2fa_scan_image_or_use_code"),
@@ -48,13 +57,12 @@ const EnableTwoFactorModal = ({ onEnable, onCancel }: EnableTwoFactorModalProps)
};
const [step, setStep] = useState(SetupStep.ConfirmPassword);
const [password, setPassword] = useState("");
const [totpCode, setTotpCode] = useState("");
const [dataUri, setDataUri] = useState("");
const [secret, setSecret] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
async function handleSetup(e: SyntheticEvent) {
async function handleSetup(e: React.FormEvent) {
e.preventDefault();
if (isSubmitting) {
@@ -88,10 +96,10 @@ const EnableTwoFactorModal = ({ onEnable, onCancel }: EnableTwoFactorModalProps)
}
}
async function handleEnable(e: SyntheticEvent) {
e.preventDefault();
async function handleEnable({ totpCode }: EnableTwoFactorValues, e: BaseSyntheticEvent | undefined) {
e?.preventDefault();
if (isSubmitting || totpCode.length !== 6) {
if (isSubmitting) {
return;
}
@@ -158,64 +166,43 @@ const EnableTwoFactorModal = ({ onEnable, onCancel }: EnableTwoFactorModalProps)
<p className="text-center font-mono text-xs">{secret}</p>
</>
</WithStep>
<WithStep step={SetupStep.EnterTotpCode} current={step}>
<form onSubmit={handleEnable}>
<Form handleSubmit={handleEnable} form={form}>
<WithStep step={SetupStep.EnterTotpCode} current={step}>
<div className="mb-4">
<label htmlFor="code" className="mt-4 block text-sm font-medium text-gray-700">
{t("code")}
</label>
<div className="mt-1">
<input
type="text"
name="code"
id="code"
required
value={totpCode}
maxLength={6}
minLength={6}
inputMode="numeric"
onInput={(e) => setTotpCode(e.currentTarget.value)}
className="block w-full rounded-sm border-gray-300 text-sm"
autoComplete="one-time-code"
/>
</div>
<TwoFactor center />
{errorMessage && <p className="mt-1 text-sm text-red-700">{errorMessage}</p>}
</div>
</form>
</WithStep>
</WithStep>
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<WithStep step={SetupStep.ConfirmPassword} current={step}>
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={handleSetup}
disabled={password.length === 0 || isSubmitting}>
{t("continue")}
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<WithStep step={SetupStep.ConfirmPassword} current={step}>
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={handleSetup}
disabled={password.length === 0 || isSubmitting}>
{t("continue")}
</Button>
</WithStep>
<WithStep step={SetupStep.DisplayQrCode} current={step}>
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={() => setStep(SetupStep.EnterTotpCode)}>
{t("continue")}
</Button>
</WithStep>
<WithStep step={SetupStep.EnterTotpCode} current={step}>
<Button type="submit" className="ltr:ml-2 rtl:mr-2" disabled={isSubmitting}>
{t("enable")}
</Button>
</WithStep>
<Button color="secondary" onClick={onCancel}>
{t("cancel")}
</Button>
</WithStep>
<WithStep step={SetupStep.DisplayQrCode} current={step}>
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={() => setStep(SetupStep.EnterTotpCode)}>
{t("continue")}
</Button>
</WithStep>
<WithStep step={SetupStep.EnterTotpCode} current={step}>
<Button
type="submit"
className="ltr:ml-2 rtl:mr-2"
onClick={handleEnable}
disabled={totpCode.length !== 6 || isSubmitting}>
{t("enable")}
</Button>
</WithStep>
<Button color="secondary" onClick={onCancel}>
{t("cancel")}
</Button>
</div>
</div>
</Form>
</DialogContent>
</Dialog>
);
@@ -19,10 +19,10 @@ const TwoFactorAuthAPI = {
});
},
async disable(password: string) {
async disable(password: string, code: string) {
return fetch("/api/auth/two-factor/totp/disable", {
method: "POST",
body: JSON.stringify({ password }),
body: JSON.stringify({ password, code }),
headers: {
"Content-Type": "application/json",
},
@@ -6,7 +6,7 @@ const TwoFactorModalHeader = ({ title, description }: { title: string; descripti
return (
<div className="mb-4 sm:flex sm:items-start">
<div className="bg-brand text-brandcontrast dark:bg-darkmodebrand dark:text-darkmodebrandcontrast mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-opacity-5 sm:mx-0 sm:h-10 sm:w-10">
<ShieldCheckIcon className="h-6 w-6 text-black" />
<ShieldCheckIcon className="h-6 w-6 text-white" />
</div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 className="font-cal text-lg font-medium leading-6 text-gray-900" id="modal-title">
@@ -4,6 +4,7 @@ import { trpc } from "@calcom/trpc/react";
import Badge from "@calcom/ui/Badge";
import Button from "@calcom/ui/Button";
/** @deprecated Use `packages/features/ee/teams/components/DisableTeamImpersonation.tsx` */
const DisableTeamImpersonation = ({ teamId, memberId }: { teamId: number; memberId: number }) => {
const { t } = useLocale();
@@ -13,6 +13,7 @@ type MembershipRoleOption = {
value: MembershipRole;
};
/** @deprecated Use `packages/features/ee/teams/components/MemberChangeRoleModal.tsx` */
export default function MemberChangeRoleModal(props: {
isOpen: boolean;
currentMember: MembershipRole;
@@ -26,6 +26,7 @@ type MembershipRoleOption = {
const _options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }, { value: "OWNER" }];
/** @deprecated Use `packages/features/ee/teams/components/MemberInvitationModal.tsx` */
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
const [errorMessage, setErrorMessage] = useState("");
const { t, i18n } = useLocale();
@@ -33,6 +33,7 @@ interface Props {
member: inferQueryOutput<"viewer.teams.get">["members"][number];
}
/** @deprecated Use `packages/features/ee/teams/components/MemberListItem.tsx` */
export default function MemberListItem(props: Props) {
const { t } = useLocale();
+1
View File
@@ -10,6 +10,7 @@ interface Props {
color?: PillColor;
}
/** @deprecated Use `packages/features/ee/teams/components/TeamPill.tsx` */
export default function TeamPill(props: Props) {
return (
<div
@@ -19,6 +19,7 @@ interface Props {
teamId: number;
}
/** @deprecated Use `packages/features/ee/teams/components/UpgradeToFlexibleProModal.tsx` */
export function UpgradeToFlexibleProModal(props: Props) {
const { t } = useLocale();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
+12 -48
View File
@@ -1,4 +1,3 @@
import classnames from "classnames";
import Link from "next/link";
import { TeamPageProps } from "pages/team/[slug]";
import React from "react";
@@ -6,11 +5,10 @@ import React from "react";
import { WEBAPP_URL } from "@calcom/lib/constants";
import Button from "@calcom/ui/Button";
import { Icon } from "@calcom/ui/Icon";
import { Avatar } from "@calcom/ui/v2";
import { useLocale } from "@lib/hooks/useLocale";
import Avatar from "@components/ui/Avatar";
type TeamType = TeamPageProps["team"];
type MembersType = TeamType["members"];
type MemberType = MembersType[number];
@@ -19,47 +17,20 @@ const Team = ({ team }: TeamPageProps) => {
const { t } = useLocale();
const Member = ({ member }: { member: MemberType }) => {
const classes = classnames(
"group",
"relative",
"flex flex-col",
"space-y-4",
"p-4",
"min-w-full sm:min-w-64 sm:max-w-64",
"bg-white dark:bg-neutral-800 dark:border-neutral-700 dark:bg-opacity-8",
"border border-neutral-200",
"hover:cursor-pointer",
"hover:border-brand dark:border-neutral-700 dark:hover:border-neutral-600",
"rounded-sm",
"hover:shadow-md"
);
return (
<Link key={member.id} href={`/${member.username}`}>
<div className={classes}>
<Icon.FiArrowRight
className={classnames(
"text-black dark:text-white",
"absolute top-4 right-4",
"h-4 w-4",
"transition-opacity",
"opacity-0 group-hover:block group-hover:opacity-100"
)}
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex h-full flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
<Avatar
size="md"
alt={member.name || ""}
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
/>
<div>
<Avatar
alt={member.name || ""}
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
className="-mt-4 h-12 w-12"
/>
<section className="line-clamp-4 mt-2 w-full space-y-1">
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
<p className="text-sm font-normal text-neutral-500 dark:text-white">
{member.bio || t("user_from_team", { user: member.name, team: team.name })}
</p>
</section>
</div>
<section className="line-clamp-4 mt-2 w-full space-y-1">
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
<p className="line-clamp-3 overflow-ellipsis text-sm font-normal text-neutral-500 dark:text-white">
{member.bio || t("user_from_team", { user: member.name, team: team.name })}
</p>
</section>
</div>
</Link>
);
@@ -82,13 +53,6 @@ const Team = ({ team }: TeamPageProps) => {
return (
<div>
<Members members={team.members} />
{team.eventTypes.length > 0 && (
<aside className="mt-8 text-center dark:text-white">
<Button color="secondary" href={`/team/${team.slug}`} shallow={true} StartIcon={Icon.FiArrowLeft}>
{t("go_back")}
</Button>
</aside>
)}
</div>
);
};

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