diff --git a/apps/web/components/booking/BookingDescription.tsx b/apps/web/components/booking/BookingDescription.tsx index 5c9f067a4c..37c33c7093 100644 --- a/apps/web/components/booking/BookingDescription.tsx +++ b/apps/web/components/booking/BookingDescription.tsx @@ -102,7 +102,7 @@ const BookingDescription: FC = (props) => { )} /> -
+
diff --git a/apps/web/components/eventtype/EventSetupTab.tsx b/apps/web/components/eventtype/EventSetupTab.tsx index e814ec822e..9e9f19eaa9 100644 --- a/apps/web/components/eventtype/EventSetupTab.tsx +++ b/apps/web/components/eventtype/EventSetupTab.tsx @@ -1,6 +1,7 @@ import { useAutoAnimate } from "@formkit/auto-animate/react"; import { zodResolver } from "@hookform/resolvers/zod"; import { isValidPhoneNumber } from "libphonenumber-js"; +import MarkdownIt from "markdown-it"; import { Trans } from "next-i18next"; import Link from "next/link"; import type { EventTypeSetupProps, FormValues } from "pages/event-types/[type]"; @@ -14,13 +15,16 @@ import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/ap import { CAL_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { slugify } from "@calcom/lib/slugify"; -import { Button, Label, Select, SettingsToggle, Skeleton, TextField } from "@calcom/ui"; +import turndown from "@calcom/lib/turndownService"; +import { Button, Editor, Label, Select, SettingsToggle, Skeleton, TextField } from "@calcom/ui"; import { FiEdit2, FiCheck, FiX, FiPlus } from "@calcom/ui/components/icon"; import { EditLocationDialog } from "@components/dialog/EditLocationDialog"; import type { SingleValueLocationOption, LocationOption } from "@components/ui/form/LocationSelect"; import LocationSelect from "@components/ui/form/LocationSelect"; +const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); + const getLocationFromType = ( type: EventLocationType["type"], locationOptions: Pick["locationOptions"] @@ -272,12 +276,15 @@ export const EventSetupTab = ( defaultValue={eventType.title} {...formMethods.register("title")} /> - +
+ + md.render(formMethods.getValues("description") || eventType.description || "")} + setText={(value: string) => formMethods.setValue("description", turndown(value))} + excludedToolbarItems={["blockType"]} + placeholder={t("quick_video_meeting")} + /> +
+ title={type.title}>
); diff --git a/apps/web/pages/settings/my-account/profile.tsx b/apps/web/pages/settings/my-account/profile.tsx index 2dffbf2926..bda681715e 100644 --- a/apps/web/pages/settings/my-account/profile.tsx +++ b/apps/web/pages/settings/my-account/profile.tsx @@ -41,7 +41,7 @@ import { FiAlertTriangle, FiTrash2 } from "@calcom/ui/components/icon"; import TwoFactor from "@components/auth/TwoFactor"; import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability"; -const md = new MarkdownIt("default", { html: true, breaks: true }); +const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); const SkeletonLoader = ({ title, description }: { title: string; description: string }) => { return ( diff --git a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx index fe16070ecb..13dd714b7d 100644 --- a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx +++ b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx @@ -1,6 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { SchedulingType } from "@prisma/client"; import { isValidPhoneNumber } from "libphonenumber-js"; +import MarkdownIt from "markdown-it"; import { useRouter } from "next/router"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -9,6 +10,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useTypedQuery } from "@calcom/lib/hooks/useTypedQuery"; import { HttpError } from "@calcom/lib/http-error"; import slugify from "@calcom/lib/slugify"; +import turndown from "@calcom/lib/turndownService"; import { createEventTypeInput } from "@calcom/prisma/zod/custom/eventtype"; import { trpc } from "@calcom/trpc/react"; import { @@ -20,10 +22,12 @@ import { Form, RadioGroup as RadioArea, showToast, - TextAreaField, TextField, + Editor, } from "@calcom/ui"; +const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); + // this describes the uniform data needed to create a new event type on Profile or Team export interface EventTypeParent { teamId: number | null | undefined; // if undefined, then it's a profile @@ -167,10 +171,11 @@ export default function CreateEventTypeDialog() { /> )} - md.render(form.getValues("description") || "")} + setText={(value: string) => form.setValue("description", turndown(value))} + excludedToolbarItems={["blockType", "link"]} placeholder={t("quick_video_meeting")} - {...register("description")} />
@@ -198,26 +203,26 @@ export default function CreateEventTypeDialog() { message={form.formState.errors.schedulingType.message} /> )} - + - {t("collective")} + {t("collective")}

{t("collective_description")}

- {t("round_robin")} + {t("round_robin")}

{t("round_robin_description")}

)}
-
+
diff --git a/packages/features/eventtypes/components/EventTypeDescription.tsx b/packages/features/eventtypes/components/EventTypeDescription.tsx index 85dca8a8cb..757401218c 100644 --- a/packages/features/eventtypes/components/EventTypeDescription.tsx +++ b/packages/features/eventtypes/components/EventTypeDescription.tsx @@ -1,4 +1,5 @@ import { Prisma, SchedulingType } from "@prisma/client"; +import MarkdownIt from "markdown-it"; import { useMemo } from "react"; import { FormattedNumber, IntlProvider } from "react-intl"; import { z } from "zod"; @@ -28,9 +29,16 @@ export type EventTypeDescriptionProps = { seatsPerTimeSlot?: number; }; className?: string; + shortenDescription?: true; }; -export const EventTypeDescription = ({ eventType, className }: EventTypeDescriptionProps) => { +const md = new MarkdownIt("default", { html: true, breaks: false, linkify: true }); + +export const EventTypeDescription = ({ + eventType, + className, + shortenDescription, +}: EventTypeDescriptionProps) => { const { t } = useLocale(); const recurringEvent = useMemo( @@ -44,10 +52,17 @@ export const EventTypeDescription = ({ eventType, className }: EventTypeDescript <>
{eventType.description && ( -

- {eventType.description.substring(0, 300)} - {eventType.description.length > 300 && "..."} -

+

<\/p>|\n/g, " ")) + : md.render(eventType.description), + }} + /> )}
    {eventType.metadata?.multipleDuration ? ( diff --git a/packages/prisma/middleware/eventTypeDescriptionParseAndSanitize.ts b/packages/prisma/middleware/eventTypeDescriptionParseAndSanitize.ts index da5813d1af..4f21a8873c 100644 --- a/packages/prisma/middleware/eventTypeDescriptionParseAndSanitize.ts +++ b/packages/prisma/middleware/eventTypeDescriptionParseAndSanitize.ts @@ -1,13 +1,7 @@ import type { PrismaClient, EventType } from "@prisma/client"; import MarkdownIt from "markdown-it"; -const md = new MarkdownIt("zero").enable([ - // - "emphasis", - "list", - "newline", - "strikethrough", -]); +const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); function parseAndSanitize(description: string) { const parsedMarkdown = md.render(description); diff --git a/packages/ui/components/editor/Editor.tsx b/packages/ui/components/editor/Editor.tsx index b709f7dd37..1ae470d3d9 100644 --- a/packages/ui/components/editor/Editor.tsx +++ b/packages/ui/components/editor/Editor.tsx @@ -30,6 +30,7 @@ export type TextEditorProps = { excludedToolbarItems?: string[]; variables?: string[]; height?: string; + placeholder?: string; }; const editorConfig = { @@ -67,7 +68,7 @@ export const Editor = (props: TextEditorProps) => {
    } - placeholder="" + placeholder={
    {props.placeholder || ""}
    } />