From 90f1cb6dd072db9da4106948ce377a27f3dbb88b Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Wed, 15 Sep 2021 18:11:04 +0100 Subject: [PATCH 01/24] Update README.md (#657) --- README.md | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 7222ca9187..b613dc5b40 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,21 @@

- Logo + Logo + -

Calendso

+

Cal.com (formerly Calendso)

The open-source Calendly alternative.
- Learn more » + Learn more »

Slack · - Website + Website · Issues

@@ -28,16 +29,24 @@ License Commits-per-month - Pricing + Pricing

## About The Project -calendso-screenshot +booking-screen -Let's face it: Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes and even calls with our families. However, most tools are very limited in terms of control and customisations. That's where Calendso 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. Calendso is to Calendly what GitLab is to GitHub. + +# Scheduling infrastructure for absolutely everyone. + +The open source Calendly alternative. You are in charge +of your own data, workflow and appearance. + +Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes and even calls with our families. However, most tools are very limited in terms of control and customisations. + +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 @@ -54,9 +63,9 @@ Let's face it: Calendly and other scheduling tools are awesome. It made our live ## Stay Up-to-Date -Calendso is currently in alpha. Watch **releases** of this repository to be notified for future updates: +Cal officially launched as v.1.0 on 15th of September, however a lot of new features are coming. Watch **releases** of this repository to be notified for future updates: -![calendso-star-github](https://user-images.githubusercontent.com/8019099/116010176-5d9c9900-a615-11eb-92d0-aa0e892f7056.gif) +![cal-star-github](https://user-images.githubusercontent.com/8019099/116010176-5d9c9900-a615-11eb-92d0-aa0e892f7056.gif) @@ -66,7 +75,7 @@ To get a local copy up and running, please follow these simple steps. ### Prerequisites -Here is what you need to be able to run Calendso. +Here is what you need to be able to run Cal. - Node.js - PostgreSQL @@ -113,7 +122,7 @@ yarn dx 1. Create a free account with [Heroku](https://www.heroku.com/). 2. Create a new app. - Google Chrome — CleanShotX | 2021-04-20 at 02 01 56 + Create an App 3. In your new app, go to `Overview` and next to `Installed add-ons`, click `Configure Add-ons`. We need this to set up our database. ![image](https://user-images.githubusercontent.com/16905768/115323232-a53ba480-a17f-11eb-98db-58e2f8c52426.png) @@ -122,7 +131,7 @@ yarn dx ![image](https://user-images.githubusercontent.com/16905768/115323126-5beb5500-a17f-11eb-8030-7380310807a9.png) 5. Once the pop-up appears, click `Submit Order Form` - plan name should be `Hobby Dev - Free`. - Google Chrome — CleanShotX | 2021-04-20 at 02 04 29 + Submit Order Form 6. Once you completed the above steps, click on your newly created `Heroku Postgres` and go to its `Settings`. ![image](https://user-images.githubusercontent.com/16905768/115323367-e92ea980-a17f-11eb-9ff4-dec95f2ec349.png) @@ -198,7 +207,7 @@ yarn dx ### Docker -The Docker configuration for Calendso is an effort powered by people within the community. Calendso does not provide official support for Docker, but we will accept fixes and documentation. Use at your own risk. +The Docker configuration for Cal is an effort powered by people within the community. Cal.com, Inc. does not provide official support for Docker, but we will accept fixes and documentation. Use at your own risk. The Docker configuration can be found [in our docker repository](https://github.com/calendso/docker). @@ -206,7 +215,7 @@ The Docker configuration can be found [in our docker repository](https://github. [![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) -You can deploy Calendso 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 Calendso on their platform. +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. @@ -264,7 +273,7 @@ Contributions are what make the open source community such an amazing place to b 10. Also add the redirect URL given above as a whitelist URL and enable "Subdomain check". Make sure, it says "saved" below the form. 11. You don't need to provide basic information about your app. Instead click at "Scopes" and then at "+ Add Scopes". On the left, click the category "Meeting" and check the scope `meeting:write`. 12. Click "Done". -13. You're good to go. Now you can easily add your Zoom integration in the Calendso settings. +13. You're good to go. Now you can easily add your Zoom integration in the Cal.com settings. @@ -276,14 +285,12 @@ Distributed under the MIT License. See `LICENSE` for more information. ## Acknowledgements -Special thanks to these amazing projects which help power Calendso: +Special thanks to these amazing projects which help power Cal.com: -[](https://vercel.com/?utm_source=calend-so&utm_campaign=oss) +[](https://vercel.com/?utm_source=calend-so&utm_campaign=oss) - [Vercel](https://vercel.com/?utm_source=calend-so&utm_campaign=oss) - [Next.js](https://nextjs.org/) - [Day.js](https://day.js.org/) - [Tailwind CSS](https://tailwindcss.com/) - [Prisma](https://prisma.io/) - -[product-screenshot]: https://i.imgur.com/4yvFj2E.png From 1d74f1a82444afa9d2d7f7cc8fa72bd4ee21dca2 Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Wed, 15 Sep 2021 18:16:57 +0100 Subject: [PATCH 02/24] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b613dc5b40..76180709ba 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ That's where Cal.com comes in. Self-hosted or hosted by us. White-label by desig #### Support us on [Product Hunt](https://www.producthunt.com/posts/calendso?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-calendso) -Calendso - The open source Calendly alternative | Product Hunt Calendso - The open source Calendly alternative | Product Hunt Calendso - The open source Calendly alternative | Product Hunt +Calendso - The open source Calendly alternative | Product Hunt Calendso - The open source Calendly alternative | Product Hunt Cal.com - The open source Calendly alternative | Product Hunt ### Built With From 9fcd458d252e04da2790e2cbbc1775a279f4ed00 Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Wed, 15 Sep 2021 19:18:16 +0100 Subject: [PATCH 03/24] renamed more calendso to cal.com (#659) --- .env.example | 4 ++-- README.md | 8 +++----- components/Logo.tsx | 4 ++-- components/booking/pages/BookingPage.tsx | 2 +- components/seo/head-seo.tsx | 2 +- components/team/EditTeam.tsx | 4 ++-- components/ui/PoweredByCalendso.tsx | 4 ++-- lib/config/next-seo.config.ts | 2 +- pages/404.tsx | 6 ++---- pages/auth/login.tsx | 2 +- pages/success.tsx | 2 +- 11 files changed, 18 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index ed0977341b..15b02c6846 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,7 @@ BASE_URL='http://localhost:3000' # Required for Vercel hosting - set NEXTAUTH_URL to equal your BASE_URL # NEXTAUTH_URL='http://localhost:3000' -# Remove this var if you don't want Calendso to collect anonymous usage +# Remove this var if you don't want Cal to collect anonymous usage NEXT_PUBLIC_TELEMETRY_KEY=js.2pvs2bbpqq1zxna97wcml.oi2jzirnbj1ev4tc57c5r # Used for the Office 365 / Outlook.com Calendar integration @@ -21,7 +21,7 @@ ZOOM_CLIENT_SECRET= # E-mail settings -# Calendso uses nodemailer (@see https://nodemailer.com/about/) to provide email sending. As such we are trying to +# Cal uses nodemailer (@see https://nodemailer.com/about/) to provide email sending. As such we are trying to # allow access to the nodemailer transports from the .env file. E-mail templates are accessible within lib/emails/ # Configures the global From: header whilst sending emails. diff --git a/README.md b/README.md index 76180709ba..b4d6789103 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@

- Join Calendso Slack + Join Cal.com Slack Product Hunt Github Stars Hacker News @@ -38,13 +38,12 @@ booking-screen - # Scheduling infrastructure for absolutely everyone. The open source Calendly alternative. You are in charge of your own data, workflow and appearance. -Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes and even calls with our families. However, most tools are very limited in terms of control and customisations. +Calendly and other scheduling tools are awesome. It made our lives massively easier. We're using it for business meetings, seminars, yoga classes and even calls with our families. However, most tools are very limited in terms of control and customisations. 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. @@ -90,12 +89,11 @@ You will also need Google API credentials. You can get this from the [Google API > - **Requires Docker to be installed** > - Will start a local Postgres instance with a few test users - the credentials will be logged in the console - ```bash git clone git@github.com:calendso/calendso.git cd calendso yarn -yarn dx +yarn dx ``` #### Manual diff --git a/components/Logo.tsx b/components/Logo.tsx index 23c26a10e4..2d99aa2eaa 100644 --- a/components/Logo.tsx +++ b/components/Logo.tsx @@ -4,8 +4,8 @@ export default function Logo({ small }: { small?: boolean }) { Calendso diff --git a/components/booking/pages/BookingPage.tsx b/components/booking/pages/BookingPage.tsx index dceb54c206..c51a5aa653 100644 --- a/components/booking/pages/BookingPage.tsx +++ b/components/booking/pages/BookingPage.tsx @@ -148,7 +148,7 @@ const BookingPage = (props: any): JSX.Element => { {rescheduleUid ? "Reschedule" : "Confirm"} your {props.eventType.title} with {props.profile.name}{" "} - | Calendso + | Cal.com diff --git a/components/seo/head-seo.tsx b/components/seo/head-seo.tsx index 5155e70426..631369e897 100644 --- a/components/seo/head-seo.tsx +++ b/components/seo/head-seo.tsx @@ -87,7 +87,7 @@ export const HeadSeo: React.FC = (props) => nextSeoProps = {}, } = props; - const pageTitle = title + " | Calendso"; + const pageTitle = title + " | Cal.com"; let seoObject = buildSeoMeta({ title: pageTitle, image, description, canonical, siteName }); if (name && avatar) { diff --git a/components/team/EditTeam.tsx b/components/team/EditTeam.tsx index cb3ffa0e5f..02d96d7d36 100644 --- a/components/team/EditTeam.tsx +++ b/components/team/EditTeam.tsx @@ -242,9 +242,9 @@ export default function EditTeam(props: { team: Team | undefined | null; onClose

-

Hide all Calendso branding from your public pages.

+

Hide all Cal.com branding from your public pages.


diff --git a/components/ui/PoweredByCalendso.tsx b/components/ui/PoweredByCalendso.tsx index 1e0ce6ab23..fdaf98ceab 100644 --- a/components/ui/PoweredByCalendso.tsx +++ b/components/ui/PoweredByCalendso.tsx @@ -9,13 +9,13 @@ const PoweredByCalendso = () => ( style={{ top: -2 }} className="dark:hidden w-auto inline h-3 relative" src="/calendso-logo-word.svg" - alt="Calendso Logo" + alt="Cal.com Logo" /> Calendso Logo diff --git a/lib/config/next-seo.config.ts b/lib/config/next-seo.config.ts index 669c0af454..b87f6bc430 100644 --- a/lib/config/next-seo.config.ts +++ b/lib/config/next-seo.config.ts @@ -15,7 +15,7 @@ export const seoConfig: { defaultNextSeo: DefaultSeoProps; } = { headSeo: { - siteName: "Calendso", + siteName: "Cal.com", }, defaultNextSeo: { twitter: { diff --git a/pages/404.tsx b/pages/404.tsx index a2f79a0cc1..4b332fcfcc 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -54,7 +54,7 @@ export default function Custom404() { Check for spelling mistakes or go back to the previous page. ) : ( - + The username calendso.com{username} is still available. Register now. @@ -65,9 +65,7 @@ export default function Custom404() { {!isEventType404 && (
  • - +
    diff --git a/pages/success.tsx b/pages/success.tsx index e8a311ca1f..84d3b608ae 100644 --- a/pages/success.tsx +++ b/pages/success.tsx @@ -226,7 +226,7 @@ export default function Success(props: inferSSRProps) )} {!props.hideBranding && ( )} From f6fe519c4c3a4ca26bbf59ad0c9defff9fde7947 Mon Sep 17 00:00:00 2001 From: Peer Richelsen Date: Wed, 15 Sep 2021 19:21:58 +0100 Subject: [PATCH 04/24] calendso to cal --- pages/404.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/404.tsx b/pages/404.tsx index 4b332fcfcc..630d2e0c2a 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -55,8 +55,8 @@ export default function Custom404() { ) : ( - The username calendso.com{username} is still - available. Register now. + The username cal.com{username} is still available.{" "} + Register now. )} From cf7f5ae53cf55c862c6f44c23c9b6ff942fac61e Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Wed, 15 Sep 2021 21:35:55 +0100 Subject: [PATCH 05/24] Replace all instances of calendso.com with cal.com and add a new logo for Cal.com emails (#662) --- .env.example | 2 +- .github/ISSUE_TEMPLATE/questions.md | 2 +- README.md | 2 +- calendso.yaml | 8 ++++---- components/DonateBanner.tsx | 4 ++-- components/Shell.tsx | 4 ++-- components/seo/head-seo.tsx | 2 +- components/ui/PoweredByCalendso.tsx | 2 +- ee/LICENSE | 2 +- ee/README.md | 8 ++++---- lib/emails/EventAttendeeMail.ts | 2 +- lib/emails/EventOrganizerMail.ts | 2 +- lib/emails/EventRejectionMail.ts | 2 +- pages/404.tsx | 8 ++++---- pages/integrations/index.tsx | 2 +- pages/settings/embed.tsx | 2 +- pages/settings/profile.tsx | 4 ++-- public/cal-logo-word.svg | 9 +++++++++ 18 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 public/cal-logo-word.svg diff --git a/.env.example b/.env.example index 15b02c6846..1c1126b585 100644 --- a/.env.example +++ b/.env.example @@ -25,7 +25,7 @@ ZOOM_CLIENT_SECRET= # allow access to the nodemailer transports from the .env file. E-mail templates are accessible within lib/emails/ # Configures the global From: header whilst sending emails. -EMAIL_FROM='notifications@yourselfhostedcalendso.com' +EMAIL_FROM='notifications@yourselfhostedcal.com' # Configure SMTP settings (@see https://nodemailer.com/smtp/). # Note: The below configuration for Office 365 has been verified to work. diff --git a/.github/ISSUE_TEMPLATE/questions.md b/.github/ISSUE_TEMPLATE/questions.md index 4097ff010f..475796de30 100644 --- a/.github/ISSUE_TEMPLATE/questions.md +++ b/.github/ISSUE_TEMPLATE/questions.md @@ -7,7 +7,7 @@ assignees: '' --- -Please do not use GitHub for asking questions, as this unnecessarily pollutes it. Instead, if you have a general question about Calendso or about Calendso's features we encourage you to post on our Slack workspace instead: [Calendso's Slack](https://calendso.com/slack). The maintainers and other community members can provide help and answer your questions there. +Please do not use GitHub for asking questions, as this unnecessarily pollutes it. Instead, if you have a general question about Calendso or about Calendso's features we encourage you to post on our Slack workspace instead: [Calendso's Slack](https://cal.com/slack). The maintainers and other community members can provide help and answer your questions there. If you've discovered a bug or would like to propose a change/new feature please use one of the other issue templates. diff --git a/README.md b/README.md index b4d6789103..136dd36c8d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@

    - Join Cal.com Slack + Join Cal.com Slack Product Hunt Github Stars Hacker News diff --git a/calendso.yaml b/calendso.yaml index 030ce2d26a..aec371c9aa 100644 --- a/calendso.yaml +++ b/calendso.yaml @@ -4,12 +4,12 @@ info: description: The open source Calendly alternative. contact: name: Support - email: support@calendso.com + email: support@cal.com license: name: MIT License url: 'https://opensource.org/licenses/MIT' version: 1.0.0 - termsOfService: 'https://calendso.com/terms' + termsOfService: 'https://cal.com/terms' server: url: 'http://localhost:{port}' description: Local Development Server @@ -205,7 +205,7 @@ paths: integration: google_calendar name: Birthdays - selected: true - externalId: bailey@calendso.com + externalId: bailey@cal.com integration: google_calendar name: Calendso primary: true @@ -1009,7 +1009,7 @@ paths: required: true description: The team which you wish to list members of servers: - - url: 'https://app.calendso.com' + - url: 'https://app.cal.com' description: Production components: securitySchemes: {} diff --git a/components/DonateBanner.tsx b/components/DonateBanner.tsx index 41675d9a39..90db7cca12 100644 --- a/components/DonateBanner.tsx +++ b/components/DonateBanner.tsx @@ -1,6 +1,6 @@ import { GiftIcon } from "@heroicons/react/outline"; export default function DonateBanner() { - if (location.hostname.endsWith(".calendso.com")) { + if (location.hostname.endsWith(".cal.com")) { return null; } @@ -27,7 +27,7 @@ export default function DonateBanner() { Donate diff --git a/components/Shell.tsx b/components/Shell.tsx index a8eb7219c0..c154c19f11 100644 --- a/components/Shell.tsx +++ b/components/Shell.tsx @@ -276,7 +276,7 @@ function UserDropdown({ small, bottom }: { small?: boolean; bottom?: boolean }) {({ active }) => ( {({ active }) => ( { return ( encodeURIComponent("Meet **" + name + "**
    " + description).replace(/'/g, "%27") + - ".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" + + ".png?md=1&images=https%3A%2F%2Fcal.com%2Fcalendso-logo-white.svg&images=" + encodeURIComponent(avatar) ); }; diff --git a/components/ui/PoweredByCalendso.tsx b/components/ui/PoweredByCalendso.tsx index fdaf98ceab..dd75088b69 100644 --- a/components/ui/PoweredByCalendso.tsx +++ b/components/ui/PoweredByCalendso.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; const PoweredByCalendso = () => (

    - + powered by{" "} # Enterprise Edition Welcome to the Enterprise Edition ("/ee") of Calendso.com. -The [/ee](https://github.com/calendso/calendso/tree/main/ee) subfolder is the place for all the **Pro** features from our [hosted](https://calendso.com/pricing) plan and [enterprise-grade](https://calendso.com/enterprise) features such as SSO, SAML, ADFS, OIDC, SCIM, SIEM, HRIS and much more. +The [/ee](https://github.com/calendso/calendso/tree/main/ee) subfolder is the place for all the **Pro** features from our [hosted](https://cal.com/pricing) plan and [enterprise-grade](https://cal.com/enterprise) features such as SSO, SAML, ADFS, OIDC, SCIM, SIEM, HRIS and much more. -> _❗ WARNING: This repository is copyrighted (unlike our [main repo](https://github.com/calendso/calendso)). You are not allowed to use this code to host your own version of app.calendso.com without obtaining a proper [license](https://calendso.com/enterprise) first❗_ +> _❗ WARNING: This repository is copyrighted (unlike our [main repo](https://github.com/calendso/calendso)). You are not allowed to use this code to host your own version of app.cal.com without obtaining a proper [license](https://cal.com/enterprise) first❗_ diff --git a/lib/emails/EventAttendeeMail.ts b/lib/emails/EventAttendeeMail.ts index cf9ea78f14..972bbf39f9 100644 --- a/lib/emails/EventAttendeeMail.ts +++ b/lib/emails/EventAttendeeMail.ts @@ -92,7 +92,7 @@ export default class EventAttendeeMail extends EventMail { `
    - Calendso Logo
    + Calendso Logo ` ); diff --git a/lib/emails/EventOrganizerMail.ts b/lib/emails/EventOrganizerMail.ts index 7c5a95994c..9f48ee3f2e 100644 --- a/lib/emails/EventOrganizerMail.ts +++ b/lib/emails/EventOrganizerMail.ts @@ -137,7 +137,7 @@ export default class EventOrganizerMail extends EventMail { `
    - Calendso Logo
    + Calendso Logo ` ); diff --git a/lib/emails/EventRejectionMail.ts b/lib/emails/EventRejectionMail.ts index f52c7eb6bb..a6d1c66ad1 100644 --- a/lib/emails/EventRejectionMail.ts +++ b/lib/emails/EventRejectionMail.ts @@ -52,7 +52,7 @@ export default class EventRejectionMail extends EventMail { `
    - Calendso Logo
    + Calendso Logo ` ); diff --git a/pages/404.tsx b/pages/404.tsx index 630d2e0c2a..855959c7cd 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -10,19 +10,19 @@ const links = [ title: "Documentation", description: "Learn how to integrate our tools with your app", icon: DocumentTextIcon, - href: "https://docs.calendso.com", + href: "https://docs.cal.com", }, { title: "API Reference", description: "A complete API reference for our libraries", icon: CodeIcon, - href: "https://api.docs.calendso.com", + href: "https://api.docs.cal.com", }, { title: "Blog", description: "Read our latest news and articles", icon: BookOpenIcon, - href: "https://calendso.com/blog", + href: "https://cal.com/blog", }, ]; @@ -117,7 +117,7 @@ export default function Custom404() {
  • ))}
  • - +
    diff --git a/pages/integrations/index.tsx b/pages/integrations/index.tsx index 250ab4f197..3d77b7e196 100644 --- a/pages/integrations/index.tsx +++ b/pages/integrations/index.tsx @@ -462,7 +462,7 @@ export default function Home({ integrations }: Props) {

    If you want to add your own App here, get in touch with us.

    diff --git a/pages/settings/embed.tsx b/pages/settings/embed.tsx index 4187fa3055..5f4fa989ac 100644 --- a/pages/settings/embed.tsx +++ b/pages/settings/embed.tsx @@ -69,7 +69,7 @@ export default function Embed(props) { Leverage our API for full control and customizability.

    - + Browse our API documentation diff --git a/pages/settings/profile.tsx b/pages/settings/profile.tsx index 3960ee506a..a303454df8 100644 --- a/pages/settings/profile.tsx +++ b/pages/settings/profile.tsx @@ -65,8 +65,8 @@ function HideBrandingInput(props: {

    {" "} To upgrade go to{" "} - - calendso.com/upgrade + + cal.com/upgrade .

    diff --git a/public/cal-logo-word.svg b/public/cal-logo-word.svg new file mode 100644 index 0000000000..bccfe813ef --- /dev/null +++ b/public/cal-logo-word.svg @@ -0,0 +1,9 @@ + + + + + + + + + From 113d18d84ee081c6be405d01d70859632c1f8e75 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Wed, 15 Sep 2021 21:36:55 +0100 Subject: [PATCH 06/24] Only show alert to upgrade when applicable and fix button (#661) Co-authored-by: Bailey Pumfleet --- pages/event-types/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/event-types/index.tsx b/pages/event-types/index.tsx index 9618fbab87..846d6da324 100644 --- a/pages/event-types/index.tsx +++ b/pages/event-types/index.tsx @@ -274,7 +274,7 @@ const EventTypesPage = (props: PageProps) => { ) }> - {props.user.plan === "FREE" && typeof window !== "undefined" && ( + {props.user.plan === "FREE" && !props.canAddEvents && typeof window !== "undefined" && ( You need to upgrade your plan to have more than one active event type.} @@ -720,7 +720,7 @@ export async function getServerSideProps(context) { createdDate: user.createdDate.toString(), }); - const canAddEvents = user.plan !== "FREE" || eventTypes.length < 1; + const canAddEvents = user.plan !== "FREE" || eventTypes[0].eventTypes.length < 1; return { props: { From b2f10eb52840d4c4194b9f694b8d2e321d35d195 Mon Sep 17 00:00:00 2001 From: Peer Richelsen Date: Wed, 15 Sep 2021 21:54:40 +0100 Subject: [PATCH 07/24] renamed in-person to link or in-person meeting --- components/booking/pages/BookingPage.tsx | 2 +- pages/event-types/[type].tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/booking/pages/BookingPage.tsx b/components/booking/pages/BookingPage.tsx index c51a5aa653..463b40afbb 100644 --- a/components/booking/pages/BookingPage.tsx +++ b/components/booking/pages/BookingPage.tsx @@ -48,7 +48,7 @@ const BookingPage = (props: any): JSX.Element => { // TODO: Move to translations const locationLabels = { - [LocationType.InPerson]: "In-person meeting", + [LocationType.InPerson]: "Link or In-person meeting", [LocationType.Phone]: "Phone call", [LocationType.GoogleMeet]: "Google Meet", [LocationType.Zoom]: "Zoom Video", diff --git a/pages/event-types/[type].tsx b/pages/event-types/[type].tsx index 8d52552b8d..d39c9974ee 100644 --- a/pages/event-types/[type].tsx +++ b/pages/event-types/[type].tsx @@ -1238,7 +1238,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => ]; const locationOptions: OptionTypeBase[] = [ - { value: LocationType.InPerson, label: "In-person meeting" }, + { value: LocationType.InPerson, label: "Link or In-person meeting" }, { value: LocationType.Phone, label: "Phone call" }, { value: LocationType.Zoom, label: "Zoom Video", disabled: true }, ]; From ebf49ca79ea80ef264e7c9b431b41b61849ed404 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Wed, 15 Sep 2021 22:58:47 +0100 Subject: [PATCH 08/24] Fixes 404 pages (#664) --- pages/[user]/[type].tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pages/[user]/[type].tsx b/pages/[user]/[type].tsx index 6197ae67c7..932eb4c427 100644 --- a/pages/[user]/[type].tsx +++ b/pages/[user]/[type].tsx @@ -117,7 +117,10 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const eventType = user.eventTypes[0]; // check this is the first event - if (user.plan === "FREE") { + + // TEMPORARILY disabled because of a bug during event create - during which users were able + // to create event types >n1. + /*if (user.plan === "FREE") { const firstEventType = await prisma.eventType.findFirst({ where: { OR: [ @@ -142,7 +145,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => notFound: true, } as const; } - } + }*/ const getWorkingHours = (providesAvailability: { availability: Availability[] }) => providesAvailability.availability && providesAvailability.availability.length ? providesAvailability.availability From e3d3fc5a114042faffc7ccd91e855f6787bfd435 Mon Sep 17 00:00:00 2001 From: Peer Richelsen Date: Thu, 16 Sep 2021 00:24:54 +0100 Subject: [PATCH 09/24] calendso to cal --- pages/getting-started.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/getting-started.tsx b/pages/getting-started.tsx index 0f19f267c3..e7eb8d1c83 100644 --- a/pages/getting-started.tsx +++ b/pages/getting-started.tsx @@ -347,7 +347,7 @@ export default function Onboarding(props: OnboardingProps) { const steps = [ { id: "welcome", - title: "Welcome to Calendso", + title: "Welcome to Cal.com", description: "Tell us what to call you and let us know what timezone you’re in. You’ll be able to edit this later.", Component: ( From 537e2951dcc4b9a835a3c08cfebbfd955ff218cd Mon Sep 17 00:00:00 2001 From: Charlie Harrington Date: Thu, 16 Sep 2021 03:13:32 -0700 Subject: [PATCH 10/24] Replace another calendso with cal (#670) --- pages/settings/profile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/settings/profile.tsx b/pages/settings/profile.tsx index a303454df8..5fbff0e258 100644 --- a/pages/settings/profile.tsx +++ b/pages/settings/profile.tsx @@ -58,7 +58,7 @@ function HideBrandingInput(props: { description={

    - In order to remove the Calendso branding from your booking pages, you need to upgrade to a paid + In order to remove the Cal branding from your booking pages, you need to upgrade to a paid account.

    From 7ae85fefeef878b535b56a9b47c7081decce02be Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Thu, 16 Sep 2021 11:14:48 +0100 Subject: [PATCH 11/24] Lacked encoding of the URL components for iso8601 dates (#669) Co-authored-by: Bailey Pumfleet --- lib/calendarClient.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/calendarClient.ts b/lib/calendarClient.ts index c7718f5b94..e9f02ca0c2 100644 --- a/lib/calendarClient.ts +++ b/lib/calendarClient.ts @@ -214,7 +214,9 @@ const MicrosoftOffice365Calendar = (credential): CalendarApiAdapter => { return { getAvailability: (dateFrom, dateTo, selectedCalendars) => { - const filter = "?startdatetime=" + dateFrom + "&enddatetime=" + dateTo; + const filter = `?startdatetime=${encodeURIComponent(dateFrom)}&enddatetime=${encodeURIComponent( + dateTo + )}`; return auth .getToken() .then((accessToken) => { From e3843f5a0eafe63b3ba9a9c193eb27decd867b44 Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Thu, 16 Sep 2021 23:01:02 +0100 Subject: [PATCH 12/24] Update README.md --- ee/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ee/README.md b/ee/README.md index 5b45b24e6b..fbd36f4c8c 100644 --- a/ee/README.md +++ b/ee/README.md @@ -1,9 +1,10 @@ -
    - - Logo -
    - Website + # Enterprise Edition From 13486d9988a11a93eeee85b0396a57c0dbad43d4 Mon Sep 17 00:00:00 2001 From: Chris S <76668588+bytesbuffer@users.noreply.github.com> Date: Fri, 17 Sep 2021 07:25:48 -0400 Subject: [PATCH 13/24] Fix issues in multiple endpoints (#679) --- pages/api/auth/signup.ts | 7 ------ pages/api/teams/[team]/membership.ts | 9 ++++++++ pages/api/user/[id].ts | 33 ++++++++++++++++++++++++++-- pages/api/user/profile.ts | 17 +++++++++----- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/pages/api/auth/signup.ts b/pages/api/auth/signup.ts index c8afa8137c..c0d8ddcf68 100644 --- a/pages/api/auth/signup.ts +++ b/pages/api/auth/signup.ts @@ -34,13 +34,6 @@ export default async function handler(req, res) { email: email, }, ], - AND: [ - { - emailVerified: { - not: null, - }, - }, - ], }, }); diff --git a/pages/api/teams/[team]/membership.ts b/pages/api/teams/[team]/membership.ts index 300e06de4b..be713f9185 100644 --- a/pages/api/teams/[team]/membership.ts +++ b/pages/api/teams/[team]/membership.ts @@ -37,6 +37,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) in: memberships.map((membership) => membership.userId), }, }, + select: { + id: true, + username: true, + name: true, + email: true, + bio: true, + avatar: true, + timeZone: true, + }, }); members = members.map((member) => { diff --git a/pages/api/user/[id].ts b/pages/api/user/[id].ts index d1598dd745..9ec73ea720 100644 --- a/pages/api/user/[id].ts +++ b/pages/api/user/[id].ts @@ -1,6 +1,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@lib/prisma"; import { getSession } from "@lib/auth"; +import { pick } from "lodash"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const session = await getSession({ req: req }); @@ -34,13 +35,41 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } if (req.method === "PATCH") { - const data = req.body.data; const updatedUser = await prisma.user.update({ where: { id: authenticatedUser.id, }, data: { - ...data, + ...pick(req.body, [ + "username", + "name", + "avatar", + "timeZone", + "weekStart", + "hideBranding", + "theme", + "completedOnboarding", + ]), + bio: req.body.description, + }, + select: { + id: true, + username: true, + name: true, + email: true, + emailVerified: true, + bio: true, + avatar: true, + timeZone: true, + weekStart: true, + startTime: true, + endTime: true, + bufferTime: true, + hideBranding: true, + theme: true, + createdDate: true, + plan: true, + completedOnboarding: true, }, }); return res.status(200).json({ message: "User Updated", data: updatedUser }); diff --git a/pages/api/user/profile.ts b/pages/api/user/profile.ts index 43562cc743..040ef33ff3 100644 --- a/pages/api/user/profile.ts +++ b/pages/api/user/profile.ts @@ -1,6 +1,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@lib/prisma"; import { getSession } from "@lib/auth"; +import { pick } from "lodash"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const session = await getSession({ req: req }); @@ -10,17 +11,23 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return; } - const description = req.body.description; - delete req.body.description; - try { await prisma.user.update({ where: { id: session.user.id, }, data: { - ...req.body, - bio: description, + ...pick(req.body, [ + "username", + "name", + "avatar", + "timeZone", + "weekStart", + "hideBranding", + "theme", + "completedOnboarding", + ]), + bio: req.body.description, }, }); } catch (e) { From 06f5559ca00f9a106e8124b3dad127428bbc5694 Mon Sep 17 00:00:00 2001 From: Bailey Pumfleet Date: Fri, 17 Sep 2021 15:41:28 +0100 Subject: [PATCH 14/24] Fix user update API call --- pages/api/user/[id].ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/user/[id].ts b/pages/api/user/[id].ts index 9ec73ea720..f764c72cf6 100644 --- a/pages/api/user/[id].ts +++ b/pages/api/user/[id].ts @@ -40,7 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) id: authenticatedUser.id, }, data: { - ...pick(req.body, [ + ...pick(req.body.data, [ "username", "name", "avatar", From 4c6bf96213b0ced3596d8dfe4345a0ca1685cef0 Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Fri, 17 Sep 2021 20:25:23 +0100 Subject: [PATCH 15/24] fixed booking buttons on mobile (#682) * fixed booking buttons on mobile * fixed mobile layout for reject and confirm booking --- pages/bookings/index.tsx | 122 ++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 26 deletions(-) diff --git a/pages/bookings/index.tsx b/pages/bookings/index.tsx index ca5b2e950c..d9dcdade03 100644 --- a/pages/bookings/index.tsx +++ b/pages/bookings/index.tsx @@ -8,7 +8,7 @@ import { Fragment } from "react"; import { Menu, Transition } from "@headlessui/react"; import { DotsHorizontalIcon } from "@heroicons/react/solid"; import classNames from "@lib/classNames"; -import { ClockIcon, XIcon } from "@heroicons/react/outline"; +import { ClockIcon, XIcon, CheckIcon, BanIcon } from "@heroicons/react/outline"; import Loader from "@components/Loader"; import { Button } from "@components/ui/Button"; import { getSession } from "@lib/auth"; @@ -89,33 +89,103 @@ export default function Bookings({ bookings }) { {!booking.confirmed && !booking.rejected && ( <> - - +
    + + +
    + + {({ open }) => ( + <> +
    + + Open options + +
    + + +
    + + {({ active }) => ( + confirmBookingHandler(booking, true)} + className={classNames( + active + ? "bg-neutral-100 text-neutral-900" + : "text-neutral-700", + "group flex items-center px-4 py-2 text-sm font-medium" + )}> + + )} + + + {({ active }) => ( + confirmBookingHandler(booking, false)} + className={classNames( + active + ? "bg-neutral-100 text-neutral-900" + : "text-neutral-700", + "group flex items-center px-4 py-2 text-sm w-full font-medium" + )}> + + )} + +
    +
    +
    + + )} +
    )} {booking.confirmed && !booking.rejected && ( -
    - - + <> +
    + + +
    {({ open }) => ( <> @@ -183,7 +253,7 @@ export default function Bookings({ bookings }) { )} -
    + )} {!booking.confirmed && booking.rejected && (
    Rejected
    From 961f297ba8054c921b2bbfff25ceec217333a765 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 17 Sep 2021 23:31:44 +0200 Subject: [PATCH 16/24] No confirmation shall be needed when rescheduling events that need confirmation (#440) * No reconfirmation needed when rescheduling * adapted success page * Parse query as string Co-authored-by: nicolas Co-authored-by: Bailey Pumfleet Co-authored-by: Peer_Rich Co-authored-by: Alex van Andel --- components/ImageUploader.tsx | 2 +- components/team/EditTeam.tsx | 2 +- components/team/TeamListItem.tsx | 4 ++-- components/ui/Alert.tsx | 2 +- components/ui/Schedule/Schedule.tsx | 1 + lib/calendarClient.ts | 4 ++-- .../CalDav/CalDavCalendarAdapter.ts | 12 +++++----- pages/api/book/event.ts | 12 +++++----- .../office365calendar/callback.ts | 1 + pages/event-types/[type].tsx | 3 +-- pages/getting-started.tsx | 11 +++++----- pages/integrations/index.tsx | 2 +- pages/settings/teams.tsx | 2 +- pages/success.tsx | 22 +++++++++---------- 14 files changed, 41 insertions(+), 39 deletions(-) diff --git a/components/ImageUploader.tsx b/components/ImageUploader.tsx index 43a2188e0d..b76bdc6eee 100644 --- a/components/ImageUploader.tsx +++ b/components/ImageUploader.tsx @@ -1,5 +1,5 @@ import Cropper from "react-easy-crop"; -import { useState, useCallback, useRef } from "react"; +import { useCallback, useRef, useState } from "react"; import Slider from "./Slider"; export default function ImageUploader({ target, id, buttonMsg, handleAvatarChange, imageRef }) { diff --git a/components/team/EditTeam.tsx b/components/team/EditTeam.tsx index 02d96d7d36..549dafa268 100644 --- a/components/team/EditTeam.tsx +++ b/components/team/EditTeam.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { ArrowLeftIcon, PlusIcon, TrashIcon } from "@heroicons/react/outline"; import ErrorAlert from "@components/ui/alerts/Error"; import { UsernameInput } from "@components/ui/UsernameInput"; diff --git a/components/team/TeamListItem.tsx b/components/team/TeamListItem.tsx index 10e1001009..052b82e111 100644 --- a/components/team/TeamListItem.tsx +++ b/components/team/TeamListItem.tsx @@ -1,9 +1,9 @@ import { - TrashIcon, DotsHorizontalIcon, + ExternalLinkIcon, LinkIcon, PencilAltIcon, - ExternalLinkIcon, + TrashIcon, } from "@heroicons/react/outline"; import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/Dropdown"; import { useState } from "react"; diff --git a/components/ui/Alert.tsx b/components/ui/Alert.tsx index a22ce26cf4..08deee22ff 100644 --- a/components/ui/Alert.tsx +++ b/components/ui/Alert.tsx @@ -1,4 +1,4 @@ -import { XCircleIcon, InformationCircleIcon, CheckCircleIcon } from "@heroicons/react/solid"; +import { CheckCircleIcon, InformationCircleIcon, XCircleIcon } from "@heroicons/react/solid"; import classNames from "classnames"; import { ReactNode } from "react"; diff --git a/components/ui/Schedule/Schedule.tsx b/components/ui/Schedule/Schedule.tsx index 20e29eaa25..c70a50041e 100644 --- a/components/ui/Schedule/Schedule.tsx +++ b/components/ui/Schedule/Schedule.tsx @@ -3,6 +3,7 @@ import Text from "@components/ui/Text"; import { PlusIcon, TrashIcon } from "@heroicons/react/outline"; import dayjs, { Dayjs } from "dayjs"; import classnames from "classnames"; + export const SCHEDULE_FORM_ID = "SCHEDULE_FORM_ID"; export const toCalendsoAvailabilityFormat = (schedule: Schedule) => { return schedule; diff --git a/lib/calendarClient.ts b/lib/calendarClient.ts index e9f02ca0c2..d28e5b3688 100644 --- a/lib/calendarClient.ts +++ b/lib/calendarClient.ts @@ -5,11 +5,11 @@ import { Credential } from "@prisma/client"; import CalEventParser from "./CalEventParser"; import { EventResult } from "@lib/events/EventManager"; import logger from "@lib/logger"; - -const log = logger.getChildLogger({ prefix: ["[lib] calendarClient"] }); import { CalDavCalendar } from "./integrations/CalDav/CalDavCalendarAdapter"; import { AppleCalendar } from "./integrations/Apple/AppleCalendarAdapter"; +const log = logger.getChildLogger({ prefix: ["[lib] calendarClient"] }); + // eslint-disable-next-line @typescript-eslint/no-var-requires const { google } = require("googleapis"); diff --git a/lib/integrations/CalDav/CalDavCalendarAdapter.ts b/lib/integrations/CalDav/CalDavCalendarAdapter.ts index 0c83a74bfe..c73ea79a56 100644 --- a/lib/integrations/CalDav/CalDavCalendarAdapter.ts +++ b/lib/integrations/CalDav/CalDavCalendarAdapter.ts @@ -1,17 +1,17 @@ -import { IntegrationCalendar, CalendarApiAdapter, CalendarEvent } from "../../calendarClient"; +import { CalendarApiAdapter, CalendarEvent, IntegrationCalendar } from "../../calendarClient"; import { symmetricDecrypt } from "@lib/crypto"; import { createAccount, - fetchCalendars, - fetchCalendarObjects, - getBasicAuthHeaders, createCalendarObject, - updateCalendarObject, deleteCalendarObject, + fetchCalendarObjects, + fetchCalendars, + getBasicAuthHeaders, + updateCalendarObject, } from "tsdav"; import { Credential } from "@prisma/client"; import ICAL from "ical.js"; -import { createEvent, DurationObject, Attendee, Person } from "ics"; +import { Attendee, createEvent, DurationObject, Person } from "ics"; import dayjs from "dayjs"; import { v4 as uuidv4 } from "uuid"; import { stripHtml } from "../../emails/helpers"; diff --git a/pages/api/book/event.ts b/pages/api/book/event.ts index 088fcc324a..268c9f21ae 100644 --- a/pages/api/book/event.ts +++ b/pages/api/book/event.ts @@ -242,13 +242,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }; // used for invitee emails } + // Initialize EventManager with credentials + const rescheduleUid = req.body.rescheduleUid; + const bookingCreateInput: Prisma.BookingCreateInput = { uid, title: evt.title, startTime: dayjs(evt.startTime).toDate(), endTime: dayjs(evt.endTime).toDate(), description: evt.description, - confirmed: !eventType.requiresConfirmation, + confirmed: !eventType.requiresConfirmation || !!rescheduleUid, location: evt.location, eventType: { connect: { @@ -375,9 +378,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } } - // Initialize EventManager with credentials const eventManager = new EventManager(user.credentials); - const rescheduleUid = req.body.rescheduleUid; + if (rescheduleUid) { // Use EventManager to conditionally use all needed integrations. const updateResults: CreateUpdateResult = await eventManager.update(evt, rescheduleUid); @@ -410,7 +412,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } } - if (eventType.requiresConfirmation) { + if (eventType.requiresConfirmation && !rescheduleUid) { await new EventOrganizerRequestMail(evt, uid).sendEmail(); } @@ -429,6 +431,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }, }); - // booking succesfull + // booking successful return res.status(201).json(booking); } diff --git a/pages/api/integrations/office365calendar/callback.ts b/pages/api/integrations/office365calendar/callback.ts index a410c214d0..64207f875d 100644 --- a/pages/api/integrations/office365calendar/callback.ts +++ b/pages/api/integrations/office365calendar/callback.ts @@ -1,6 +1,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { getSession } from "@lib/auth"; import prisma from "../../../../lib/prisma"; + const scopes = ["offline_access", "Calendars.Read", "Calendars.ReadWrite"]; export default async function handler(req: NextApiRequest, res: NextApiResponse) { diff --git a/pages/event-types/[type].tsx b/pages/event-types/[type].tsx index d39c9974ee..ad2456a173 100644 --- a/pages/event-types/[type].tsx +++ b/pages/event-types/[type].tsx @@ -3,7 +3,7 @@ import Modal from "@components/Modal"; import React, { useEffect, useRef, useState } from "react"; import Select, { OptionTypeBase } from "react-select"; import prisma from "@lib/prisma"; -import { EventTypeCustomInput, EventTypeCustomInputType, SchedulingType } from "@prisma/client"; +import { Availability, EventTypeCustomInput, EventTypeCustomInputType, SchedulingType } from "@prisma/client"; import { LocationType } from "@lib/location"; import Shell from "@components/Shell"; import { getSession } from "@lib/auth"; @@ -28,7 +28,6 @@ import { import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import timezone from "dayjs/plugin/timezone"; -import { Availability } from "@prisma/client"; import { validJson } from "@lib/jsonUtils"; import throttle from "lodash.throttle"; import "react-dates/initialize"; diff --git a/pages/getting-started.tsx b/pages/getting-started.tsx index e7eb8d1c83..d29a8b056d 100644 --- a/pages/getting-started.tsx +++ b/pages/getting-started.tsx @@ -2,15 +2,15 @@ import Head from "next/head"; import prisma from "@lib/prisma"; import { useSession } from "next-auth/client"; import { + EventType, EventTypeCreateInput, + Schedule, ScheduleCreateInput, User, UserUpdateInput, - EventType, - Schedule, } from "@prisma/client"; import { NextPageContext } from "next"; -import React, { useState, useEffect, useRef } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { validJson } from "@lib/jsonUtils"; import TimezoneSelect from "react-timezone-select"; import Text from "@components/ui/Text"; @@ -18,8 +18,6 @@ import ErrorAlert from "@components/ui/alerts/Error"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import timezone from "dayjs/plugin/timezone"; -dayjs.extend(utc); -dayjs.extend(timezone); import AddCalDavIntegration, { ADD_CALDAV_INTEGRATION_FORM_TITLE, } from "@lib/integrations/CalDav/components/AddCalDavIntegration"; @@ -33,6 +31,9 @@ import { ArrowRightIcon } from "@heroicons/react/outline"; import { getSession } from "@lib/auth"; import Button from "@components/ui/Button"; +dayjs.extend(utc); +dayjs.extend(timezone); + const DEFAULT_EVENT_TYPES = [ { title: "15 Min Meeting", diff --git a/pages/integrations/index.tsx b/pages/integrations/index.tsx index 3d77b7e196..68d83b12c3 100644 --- a/pages/integrations/index.tsx +++ b/pages/integrations/index.tsx @@ -1,7 +1,7 @@ import Link from "next/link"; import prisma from "@lib/prisma"; import Shell from "@components/Shell"; -import { useEffect, useState, useRef, useCallback } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { useSession } from "next-auth/client"; import { CheckCircleIcon, ChevronRightIcon, PlusIcon, XCircleIcon } from "@heroicons/react/solid"; import { InformationCircleIcon } from "@heroicons/react/outline"; diff --git a/pages/settings/teams.tsx b/pages/settings/teams.tsx index 2847567e24..a7a82b0c07 100644 --- a/pages/settings/teams.tsx +++ b/pages/settings/teams.tsx @@ -1,7 +1,7 @@ import { GetServerSideProps } from "next"; import Shell from "@components/Shell"; import SettingsShell from "@components/Settings"; -import { useEffect, useState, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import type { Session } from "next-auth"; import { useSession } from "next-auth/client"; import { UsersIcon } from "@heroicons/react/outline"; diff --git a/pages/success.tsx b/pages/success.tsx index 84d3b608ae..f80d4748ee 100644 --- a/pages/success.tsx +++ b/pages/success.tsx @@ -23,7 +23,7 @@ dayjs.extend(timezone); export default function Success(props: inferSSRProps) { const router = useRouter(); - const { location, name } = router.query; + const { location, name, reschedule } = router.query; const [is24h, setIs24h] = useState(false); const [date, setDate] = useState(dayjs.utc(asStringOrNull(router.query.date))); @@ -62,12 +62,14 @@ export default function Success(props: inferSSRProps) return encodeURIComponent(event.value); } + const needsConfirmation = props.eventType.requiresConfirmation && reschedule != "true"; + return ( isReady && (
    @@ -83,22 +85,18 @@ export default function Success(props: inferSSRProps) aria-labelledby="modal-headline">
    - {!props.eventType.requiresConfirmation && ( - - )} - {props.eventType.requiresConfirmation && ( - - )} + {!needsConfirmation && } + {needsConfirmation && }

    - {props.eventType.requiresConfirmation + {needsConfirmation ? props.profile.name !== null ? `${props.profile.name} still needs to confirm or reject the booking.` : "Your booking still needs to be confirmed or rejected." @@ -126,7 +124,7 @@ export default function Success(props: inferSSRProps)

    - {!props.eventType.requiresConfirmation && ( + {!needsConfirmation && (
    Add to calendar From dd9f5fe791f834688164b5f875b6a8024ebddb4d Mon Sep 17 00:00:00 2001 From: Alex Johansson Date: Sat, 18 Sep 2021 00:02:35 +0100 Subject: [PATCH 17/24] suggestion: `max-params` `3` (#647) --- .eslintrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 6cb93362fd..27082ca90a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,7 +21,8 @@ "react/react-in-jsx-scope": "off", "react/prop-types": "off", "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off" + "@typescript-eslint/explicit-module-boundary-types": "off", + "max-params": ["error", 3] }, "overrides": [ { From f6005b8c70838421bf975aa876cbfde79b628bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Fri, 17 Sep 2021 17:08:02 -0600 Subject: [PATCH 18/24] [CAL-409] Prevents usernames with special characters (#668) --- lib/slugify.ts | 2 +- pages/api/auth/signup.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/slugify.ts b/lib/slugify.ts index a0a530ef6c..c6fba1f4f0 100644 --- a/lib/slugify.ts +++ b/lib/slugify.ts @@ -1,5 +1,5 @@ export const slugify = (str: string) => { - return str.replace(/\s+/g, "-").toLowerCase(); + return str.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase(); }; export default slugify; diff --git a/pages/api/auth/signup.ts b/pages/api/auth/signup.ts index c0d8ddcf68..476bd60df1 100644 --- a/pages/api/auth/signup.ts +++ b/pages/api/auth/signup.ts @@ -1,13 +1,16 @@ -import prisma from "../../../lib/prisma"; -import { hashPassword } from "../../../lib/auth"; +import { hashPassword } from "@lib/auth"; +import prisma from "@lib/prisma"; +import slugify from "@lib/slugify"; +import { NextApiRequest, NextApiResponse } from "next"; -export default async function handler(req, res) { +export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method !== "POST") { return; } const data = req.body; - const { username, email, password } = data; + const { email, password } = data; + const username = slugify(data.username); if (!username) { res.status(422).json({ message: "Invalid username" }); From 2cf02c4f31f1429983744a24419e27b91e401274 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Sat, 18 Sep 2021 17:33:42 +0100 Subject: [PATCH 19/24] Skip failing tests for now + fix typo (#686) --- cypress/integration/booking-pages.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cypress/integration/booking-pages.spec.ts b/cypress/integration/booking-pages.spec.ts index 74657ef5fb..00437e4af2 100644 --- a/cypress/integration/booking-pages.spec.ts +++ b/cypress/integration/booking-pages.spec.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ describe("booking pages", () => { describe("free user", () => { - it("only one visibile event", () => { + it("only one visible event", () => { cy.visit("/free"); cy.get("[data-testid=event-types]").children().should("have.length", 1); cy.get('[href="/free/30min"]').should("exist"); @@ -18,7 +18,7 @@ describe("booking pages", () => { }); }); - it("/free/60min is not bookable", () => { + it.skip("/free/60min is not bookable", () => { cy.request({ method: "GET", url: "/free/60min", @@ -28,7 +28,7 @@ describe("booking pages", () => { }); }); }); - it("pro user's page has at least 2 visibile events", () => { + it("pro user's page has at least 2 visible events", () => { cy.visit("/pro"); cy.get("[data-testid=event-types]").children().should("have.length.at.least", 2); }); @@ -49,7 +49,7 @@ describe("booking pages", () => { }); }); - it("/free-first-hidden/60min is not bookable", () => { + it.skip("/free-first-hidden/60min is not bookable", () => { cy.request({ method: "GET", url: "/free-first-hidden/60min", From ed8241ac1b6508812ed827268548542e420648ad Mon Sep 17 00:00:00 2001 From: Femi Odugbesan Date: Sat, 18 Sep 2021 11:49:18 -0500 Subject: [PATCH 20/24] Fix/events from caldav not taken into consideration when checking availability (#637) * use version 1.0.6 * use logger over console log fix typing issue Co-authored-by: Bailey Pumfleet --- .../CalDav/CalDavCalendarAdapter.ts | 103 +++++++++--------- package.json | 2 +- yarn.lock | 8 +- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/lib/integrations/CalDav/CalDavCalendarAdapter.ts b/lib/integrations/CalDav/CalDavCalendarAdapter.ts index c73ea79a56..201e2b6fa1 100644 --- a/lib/integrations/CalDav/CalDavCalendarAdapter.ts +++ b/lib/integrations/CalDav/CalDavCalendarAdapter.ts @@ -17,7 +17,7 @@ import { v4 as uuidv4 } from "uuid"; import { stripHtml } from "../../emails/helpers"; import logger from "@lib/logger"; -const log = logger.getChildLogger({ prefix: ["[[lib] caldav"] }); +const log = logger.getChildLogger({ prefix: ["[lib] caldav"] }); type EventBusyDate = Record<"start" | "end", Date>; @@ -111,7 +111,7 @@ export class CalDavCalendar implements CalendarApiAdapter { id: uid, }; } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } @@ -161,7 +161,7 @@ export class CalDavCalendar implements CalendarApiAdapter { }) ); } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } @@ -193,7 +193,7 @@ export class CalDavCalendar implements CalendarApiAdapter { }) ); } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } @@ -260,7 +260,7 @@ export class CalDavCalendar implements CalendarApiAdapter { integration: this.integrationName, })); } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } @@ -281,58 +281,59 @@ export class CalDavCalendar implements CalendarApiAdapter { headers: this.headers, }); - const events = - objects && - objects?.length > 0 && - objects - .map((object) => { - if (object?.data) { - const jcalData = ICAL.parse(object.data); - const vcalendar = new ICAL.Component(jcalData); - const vevent = vcalendar.getFirstSubcomponent("vevent"); - const event = new ICAL.Event(vevent); + if (!objects || objects?.length === 0) { + return []; + } - const calendarTimezone = vcalendar.getFirstSubcomponent("vtimezone") - ? vcalendar.getFirstSubcomponent("vtimezone").getFirstPropertyValue("tzid") - : ""; + const events = objects + .map((object) => { + if (object?.data) { + const jcalData = ICAL.parse(object.data); + const vcalendar = new ICAL.Component(jcalData); + const vevent = vcalendar.getFirstSubcomponent("vevent"); + const event = new ICAL.Event(vevent); - const startDate = calendarTimezone - ? dayjs(event.startDate).tz(calendarTimezone) - : new Date(event.startDate.toUnixTime() * 1000); - const endDate = calendarTimezone - ? dayjs(event.endDate).tz(calendarTimezone) - : new Date(event.endDate.toUnixTime() * 1000); + const calendarTimezone = vcalendar.getFirstSubcomponent("vtimezone") + ? vcalendar.getFirstSubcomponent("vtimezone").getFirstPropertyValue("tzid") + : ""; - return { - uid: event.uid, - etag: object.etag, - url: object.url, - summary: event.summary, - description: event.description, - location: event.location, - sequence: event.sequence, - startDate, - endDate, - duration: { - weeks: event.duration.weeks, - days: event.duration.days, - hours: event.duration.hours, - minutes: event.duration.minutes, - seconds: event.duration.seconds, - isNegative: event.duration.isNegative, - }, - organizer: event.organizer, - attendees: event.attendees.map((a) => a.getValues()), - recurrenceId: event.recurrenceId, - timezone: calendarTimezone, - }; - } - }) - .filter((e) => e != null); + const startDate = calendarTimezone + ? dayjs(event.startDate).tz(calendarTimezone) + : new Date(event.startDate.toUnixTime() * 1000); + const endDate = calendarTimezone + ? dayjs(event.endDate).tz(calendarTimezone) + : new Date(event.endDate.toUnixTime() * 1000); + + return { + uid: event.uid, + etag: object.etag, + url: object.url, + summary: event.summary, + description: event.description, + location: event.location, + sequence: event.sequence, + startDate, + endDate, + duration: { + weeks: event.duration.weeks, + days: event.duration.days, + hours: event.duration.hours, + minutes: event.duration.minutes, + seconds: event.duration.seconds, + isNegative: event.duration.isNegative, + }, + organizer: event.organizer, + attendees: event.attendees.map((a) => a.getValues()), + recurrenceId: event.recurrenceId, + timezone: calendarTimezone, + }; + } + }) + .filter((e) => e != null); return events; } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } diff --git a/package.json b/package.json index 55c1982c6d..29520f9f9f 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "react-select": "^4.3.1", "react-timezone-select": "^1.0.7", "short-uuid": "^4.2.0", - "tsdav": "^1.0.6", + "tsdav": "1.0.6", "tslog": "^3.2.1", "uuid": "^8.3.2" }, diff --git a/yarn.lock b/yarn.lock index 588c58df73..00b00f098f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7489,10 +7489,10 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsdav@^1.0.6: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tsdav/-/tsdav-1.1.0.tgz#48fe17df07f852ff8dfddf71fae2396e79ed6735" - integrity sha512-Cc/VTFgUC/fOOFkGT/xuwrrIrG0+it7WA5ywNM4QyYWAzXVw+WmbM1pr7/7fzHA/OOVQ0a8RyPi4K1C+mFBGJw== +tsdav@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsdav/-/tsdav-1.0.6.tgz#65c22fc77d6516db234c1288ff9c9fed6730fef5" + integrity sha512-xnKE39wZtyLoyW1UClYAb2Eilx6tHzbqhO2v29P1zrmwLAsKNYUHwHb+lrmJHfZZLsbbzKWRg5dPLYRuEXmMJA== dependencies: base-64 "^1.0.0" cross-fetch "^3.1.4" From be15868ef9008a1539ebf74209ba540dfefaa6c2 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Sat, 18 Sep 2021 18:25:56 +0100 Subject: [PATCH 21/24] Revert "suggestion: `max-params` `3` (#647)" (#689) This reverts commit dd9f5fe791f834688164b5f875b6a8024ebddb4d. --- .eslintrc.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 27082ca90a..6cb93362fd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,8 +21,7 @@ "react/react-in-jsx-scope": "off", "react/prop-types": "off", "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "max-params": ["error", 3] + "@typescript-eslint/explicit-module-boundary-types": "off" }, "overrides": [ { From 7eed1b2fa6da14c502aa63d07aaca4173a074af4 Mon Sep 17 00:00:00 2001 From: Chris <76668588+bytesbuffer@users.noreply.github.com> Date: Sat, 18 Sep 2021 18:32:07 -0400 Subject: [PATCH 22/24] Prevent unauthorized event type access (#694) Co-authored-by: Bailey Pumfleet --- pages/api/availability/eventtype.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pages/api/availability/eventtype.ts b/pages/api/availability/eventtype.ts index 12bb015000..4ec9a4097e 100644 --- a/pages/api/availability/eventtype.ts +++ b/pages/api/availability/eventtype.ts @@ -10,6 +10,35 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return; } + if (!session.user?.id) { + console.error("Session is missing a user id"); + return res.status(500).json({ message: "Something went wrong" }); + } + + if (req.method !== "POST") { + const event = await prisma.eventType.findUnique({ + where: { id: req.body.id }, + include: { + users: true, + }, + }); + + if (!event) { + return res.status(404).json({ message: "No event exists matching that id." }); + } + + const isAuthorized = + event.userId === session.user.id || + event.users.find((user) => { + return user.id === session.user?.id; + }); + + if (!isAuthorized) { + console.warn(`User ${session.user.id} attempted to an access an event ${event.id} they do not own.`); + return res.status(404).json({ message: "No event exists matching that id." }); + } + } + if (req.method == "PATCH" || req.method == "POST") { const data = { title: req.body.title, From f281c49e76494674cdbc6c659c31b34527dd889c Mon Sep 17 00:00:00 2001 From: Chris <76668588+bytesbuffer@users.noreply.github.com> Date: Sun, 19 Sep 2021 10:31:45 -0400 Subject: [PATCH 23/24] Remove password reset data from response (#699) Co-authored-by: Bailey Pumfleet --- pages/api/auth/forgot-password.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/auth/forgot-password.ts b/pages/api/auth/forgot-password.ts index 54f1427a9d..83087dc8b1 100644 --- a/pages/api/auth/forgot-password.ts +++ b/pages/api/auth/forgot-password.ts @@ -69,7 +69,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) text: message, }); - return res.status(201).json({ message: "Reset Requested", data: passwordRequest }); + return res.status(201).json({ message: "Reset Requested" }); } catch (reason) { console.error(reason); return res.status(500).json({ message: "Unable to create password reset request" }); From a4b1264db123ff23441dda826dbb80783ba1118d Mon Sep 17 00:00:00 2001 From: Peer_Rich Date: Sun, 19 Sep 2021 20:48:15 +0100 Subject: [PATCH 24/24] removed arrow from dropdown (#685) --- components/ui/Dropdown.tsx | 1 - pages/event-types/index.tsx | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/components/ui/Dropdown.tsx b/components/ui/Dropdown.tsx index 2987ecc4e9..7f5dc8f0f8 100644 --- a/components/ui/Dropdown.tsx +++ b/components/ui/Dropdown.tsx @@ -29,7 +29,6 @@ export const DropdownMenuContent = forwardRef {children} - ); } diff --git a/pages/event-types/index.tsx b/pages/event-types/index.tsx index 846d6da324..b6d0f19518 100644 --- a/pages/event-types/index.tsx +++ b/pages/event-types/index.tsx @@ -357,11 +357,7 @@ const CreateNewEventDialog = ({ profiles, canAddEvents }: { profiles: Profile[]; - - Create an event type under -
    - your name or a team. -
    + Create an event type under your name or a team. {profiles.map((profile) => (