From 323524b77c4a8a26e20508251225506b88aca043 Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Tue, 24 May 2022 09:29:39 -0400 Subject: [PATCH] Redesign help menu item (#2710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Seperate help menu item and contact menu item * Add menu items * Install react-popover * Render contact only if support keys are present * Adjust contact support links * Add translations * Add embed changes * Adjust menu if helped is pressed * Add items to help menu * Change button color on selection * Create endpoint * Create feedback table * Create migration file * Write feedback to db * Remove logs * Add response message * Send feedback email * Disable submit if no rating and after submit * Add translations * Fix padding * Clean up * Clean up * Add user feedback email to .env example * Lint fixes and styles * Changed onClick function to a named function and fix style * Fix ids order * Removed commented code and changed textarea id and name * Fix id orders * Change to AND operator Co-authored-by: Omar López * Add user relation to feedback Co-authored-by: Omar López * Add migration files * Change rating to strings * Change rating to strings * Fix type errors * WIP success & error messages * Change success and error to boolans * Style messages * Add await Co-authored-by: Omar López * Remove duplicate string * Refactor import statement Co-authored-by: Omar López * Change opacity of emojis * added support@cal.com email for feedback * Add success toast * Update .env.example Co-authored-by: Omar López * Add tCRP route * tCRP send email * tCRP send email Co-authored-by: Alan Co-authored-by: Omar López Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: Peer Richelsen --- .env.example | 4 + apps/web/components/Shell.tsx | 204 ++++++++++-------- .../ee/components/support/ContactMenuItem.tsx | 13 ++ .../ee/components/support/HelpMenuItem.tsx | 194 ++++++++++++++++- .../ee/lib/helpscout/HelpscoutMenuItem.tsx | 20 +- apps/web/ee/lib/intercom/IntercomMenuItem.tsx | 25 +-- apps/web/ee/lib/zendesk/ZendeskMenuItem.tsx | 19 +- apps/web/lib/emails/email-manager.ts | 12 ++ .../lib/emails/templates/feedback-email.ts | 118 ++++++++++ apps/web/public/static/locales/en/common.json | 22 +- apps/web/server/routers/viewer.tsx | 28 +++ .../migration.sql | 10 + .../migration.sql | 2 + packages/prisma/schema.prisma | 10 + yarn.lock | 5 + 15 files changed, 536 insertions(+), 150 deletions(-) create mode 100644 apps/web/ee/components/support/ContactMenuItem.tsx create mode 100644 apps/web/lib/emails/templates/feedback-email.ts create mode 100644 packages/prisma/migrations/20220513151152_adds_feedback_table/migration.sql create mode 100644 packages/prisma/migrations/20220518201335_add_user_relationship_to_feedback/migration.sql diff --git a/.env.example b/.env.example index cebebfa0d4..72a2e0f769 100644 --- a/.env.example +++ b/.env.example @@ -70,6 +70,10 @@ NEXT_PUBLIC_ZENDESK_KEY= # Help Scout Config NEXT_PUBLIC_HELPSCOUT_KEY= +# Inbox to send user feedback +SEND_FEEDBACK_EMAIL= + + # This is used so we can bypass emails in auth flows for E2E testing # Set it to "1" if you need to run E2E tests locally NEXT_PUBLIC_IS_E2E= diff --git a/apps/web/components/Shell.tsx b/apps/web/components/Shell.tsx index beea8ff7d6..f3d11aeaaf 100644 --- a/apps/web/components/Shell.tsx +++ b/apps/web/components/Shell.tsx @@ -10,12 +10,13 @@ import { MapIcon, MoonIcon, ViewGridIcon, + QuestionMarkCircleIcon, } from "@heroicons/react/solid"; import { UserPlan } from "@prisma/client"; import { SessionContextValue, signOut, useSession } from "next-auth/react"; import Link from "next/link"; import { useRouter } from "next/router"; -import React, { Fragment, ReactNode, useEffect } from "react"; +import React, { Fragment, ReactNode, useEffect, useState } from "react"; import { Toaster } from "react-hot-toast"; import { useIsEmbed } from "@calcom/embed-core"; @@ -461,8 +462,10 @@ function UserDropdown({ small }: { small?: boolean }) { }, }); const utils = trpc.useContext(); + const [helpOpen, setHelpOpen] = useState(false); + return ( - + setHelpOpen(false)}> + + + + signOut({ callbackUrl: "/auth/logout" })} + className="flex cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"> + + + )} - - - - - - - - - - - - {t("join_our_slack")} - - - - - {t("visit_roadmap")} - - - - - - - - signOut({ callbackUrl: "/auth/logout" })} - className="flex cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"> - - ); diff --git a/apps/web/ee/components/support/ContactMenuItem.tsx b/apps/web/ee/components/support/ContactMenuItem.tsx new file mode 100644 index 0000000000..15ae451c54 --- /dev/null +++ b/apps/web/ee/components/support/ContactMenuItem.tsx @@ -0,0 +1,13 @@ +import HelpscoutMenuItem from "@ee/lib/helpscout/HelpscoutMenuItem"; +import IntercomMenuItem from "@ee/lib/intercom/IntercomMenuItem"; +import ZendeskMenuItem from "@ee/lib/zendesk/ZendeskMenuItem"; + +export default function HelpMenuItem() { + return ( + <> + + + + + ); +} diff --git a/apps/web/ee/components/support/HelpMenuItem.tsx b/apps/web/ee/components/support/HelpMenuItem.tsx index 15ae451c54..6a1d31bc20 100644 --- a/apps/web/ee/components/support/HelpMenuItem.tsx +++ b/apps/web/ee/components/support/HelpMenuItem.tsx @@ -1,13 +1,191 @@ -import HelpscoutMenuItem from "@ee/lib/helpscout/HelpscoutMenuItem"; -import IntercomMenuItem from "@ee/lib/intercom/IntercomMenuItem"; -import ZendeskMenuItem from "@ee/lib/zendesk/ZendeskMenuItem"; +import { ExternalLinkIcon, ExclamationIcon } from "@heroicons/react/solid"; +import { useState } from "react"; + +import { useLocale } from "@calcom/lib/hooks/useLocale"; +import showToast from "@calcom/lib/notification"; +import Button from "@calcom/ui/Button"; + +import classNames from "@lib/classNames"; +import { trpc } from "@lib/trpc"; + +import ContactMenuItem from "./ContactMenuItem"; export default function HelpMenuItem() { + const [rating, setRating] = useState(null); + const [comment, setComment] = useState(""); + // const [errorMessage, setErrorMessage] = useState(false); + const [disableSubmit, setDisableSubmit] = useState(true); + const { t } = useLocale(); + + const mutation = trpc.useMutation("viewer.submitFeedback"); + + const onRatingClick = (value: string) => { + setRating(value); + setDisableSubmit(false); + }; + + const sendFeedback = async (rating: string, comment: string) => { + mutation.mutate({ rating: rating, comment: comment }); + + if (mutation.isSuccess) { + setDisableSubmit(true); + showToast("Thank you, feedback submitted", "success"); + } + }; + return ( - <> - - - - +
+ + +
+
+

{t("feedback").toUpperCase()}

+

{t("comments")}

+ + +
+ + + + +
+
+ +
+ {mutation.isError && ( +
+
+ +
+
+

{t("feedback_error")}

+

{t("please_try_again")}

+
+
+ )} +
+
); } diff --git a/apps/web/ee/lib/helpscout/HelpscoutMenuItem.tsx b/apps/web/ee/lib/helpscout/HelpscoutMenuItem.tsx index 350af9ab4b..016f884da9 100644 --- a/apps/web/ee/lib/helpscout/HelpscoutMenuItem.tsx +++ b/apps/web/ee/lib/helpscout/HelpscoutMenuItem.tsx @@ -22,20 +22,12 @@ export default function HelpscoutMenuItem() { else return ( <> - - - + + {active && } ); diff --git a/apps/web/ee/lib/intercom/IntercomMenuItem.tsx b/apps/web/ee/lib/intercom/IntercomMenuItem.tsx index 65688e2488..e7e526c861 100644 --- a/apps/web/ee/lib/intercom/IntercomMenuItem.tsx +++ b/apps/web/ee/lib/intercom/IntercomMenuItem.tsx @@ -13,22 +13,13 @@ export default function IntercomMenuItem() { if (!process.env.NEXT_PUBLIC_INTERCOM_APP_ID) return null; else return ( - - - + ); } diff --git a/apps/web/ee/lib/zendesk/ZendeskMenuItem.tsx b/apps/web/ee/lib/zendesk/ZendeskMenuItem.tsx index 706495f4c2..2d7014f148 100644 --- a/apps/web/ee/lib/zendesk/ZendeskMenuItem.tsx +++ b/apps/web/ee/lib/zendesk/ZendeskMenuItem.tsx @@ -17,20 +17,11 @@ export default function ZendeskMenuItem() { else return ( <> - - - + {active && (