From 3c508568da9f669a9e02c9d8deb33e5615292430 Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Thu, 31 Aug 2023 12:04:19 +0530 Subject: [PATCH] fix: lower case slugs in teams (#11026) * fix: lower case slugs in teams Signed-off-by: Udit Takkar * fix: use slugify Signed-off-by: Udit Takkar --------- Signed-off-by: Udit Takkar --- .../pages/settings/other-team-profile-view.tsx | 3 ++- .../ee/teams/components/CreateANewTeamForm.tsx | 3 ++- .../features/ee/teams/pages/team-profile-view.tsx | 3 ++- packages/lib/slugify.ts | 12 ++++++++---- .../server/routers/viewer/teams/update.schema.ts | 7 ++++++- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/features/ee/organizations/pages/settings/other-team-profile-view.tsx b/packages/features/ee/organizations/pages/settings/other-team-profile-view.tsx index c9de131e87..aabbfaa187 100644 --- a/packages/features/ee/organizations/pages/settings/other-team-profile-view.tsx +++ b/packages/features/ee/organizations/pages/settings/other-team-profile-view.tsx @@ -13,6 +13,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { md } from "@calcom/lib/markdownIt"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import objectKeys from "@calcom/lib/objectKeys"; +import slugify from "@calcom/lib/slugify"; import turndown from "@calcom/lib/turndownService"; import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; @@ -229,7 +230,7 @@ const OtherTeamProfileView = () => { } onChange={(e) => { form.clearErrors("slug"); - form.setValue("slug", e?.target.value); + form.setValue("slug", slugify(e?.target.value, true)); }} /> diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx index ebe4e642b8..d943c567fe 100644 --- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx +++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx @@ -115,9 +115,10 @@ export const CreateANewTeamForm = () => { ? orgBranding.fullDomain.replace("https://", "").replace("http://", "") + "/" : `${extractDomainFromWebsiteUrl}/team/` }`} + value={value} defaultValue={value} onChange={(e) => { - newTeamFormMethods.setValue("slug", slugify(e?.target.value), { + newTeamFormMethods.setValue("slug", slugify(e?.target.value, true), { shouldTouch: true, }); newTeamFormMethods.clearErrors("slug"); diff --git a/packages/features/ee/teams/pages/team-profile-view.tsx b/packages/features/ee/teams/pages/team-profile-view.tsx index e86861a96f..369ee5686a 100644 --- a/packages/features/ee/teams/pages/team-profile-view.tsx +++ b/packages/features/ee/teams/pages/team-profile-view.tsx @@ -16,6 +16,7 @@ import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback"; import { md } from "@calcom/lib/markdownIt"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import objectKeys from "@calcom/lib/objectKeys"; +import slugify from "@calcom/lib/slugify"; import turndown from "@calcom/lib/turndownService"; import { MembershipRole } from "@calcom/prisma/enums"; import { trpc } from "@calcom/trpc/react"; @@ -232,7 +233,7 @@ const ProfileView = () => { } onChange={(e) => { form.clearErrors("slug"); - form.setValue("slug", e?.target.value); + form.setValue("slug", slugify(e?.target.value, true)); }} /> diff --git a/packages/lib/slugify.ts b/packages/lib/slugify.ts index a14897e34e..e43d8d57e3 100644 --- a/packages/lib/slugify.ts +++ b/packages/lib/slugify.ts @@ -1,13 +1,17 @@ -export const slugify = (str: string) => { - return str +// forDisplayingInput is used to allow user to type "-" at the end and not replace with empty space. +// For eg:- "test-slug" is the slug user wants to set but while typing "test-" would get replace to "test" becauser of replace(/-+$/, "") + +export const slugify = (str: string, forDisplayingInput?: boolean) => { + const s = str .toLowerCase() // Convert to lowercase .trim() // Remove whitespace from both sides .normalize("NFD") // Normalize to decomposed form for handling accents .replace(/\p{Diacritic}/gu, "") // Remove any diacritics (accents) from characters .replace(/[^\p{L}\p{N}\p{Zs}\p{Emoji}]+/gu, "-") // Replace any non-alphanumeric characters (including Unicode) with a dash .replace(/[\s_#]+/g, "-") // Replace whitespace, # and underscores with a single dash - .replace(/^-+/, "") // Remove dashes from start - .replace(/-+$/, ""); // Remove dashes from end + .replace(/^-+/, ""); // Remove dashes from start + + return forDisplayingInput ? s : s.replace(/-+$/, ""); // Remove dashes from end }; export default slugify; diff --git a/packages/trpc/server/routers/viewer/teams/update.schema.ts b/packages/trpc/server/routers/viewer/teams/update.schema.ts index 7da9261808..5c88cd84f5 100644 --- a/packages/trpc/server/routers/viewer/teams/update.schema.ts +++ b/packages/trpc/server/routers/viewer/teams/update.schema.ts @@ -1,11 +1,16 @@ import { z } from "zod"; +import slugify from "@calcom/lib/slugify"; + export const ZUpdateInputSchema = z.object({ id: z.number(), bio: z.string().optional(), name: z.string().optional(), logo: z.string().optional(), - slug: z.string().optional(), + slug: z + .string() + .transform((val) => slugify(val.trim())) + .optional(), hideBranding: z.boolean().optional(), hideBookATeamMember: z.boolean().optional(), isPrivate: z.boolean().optional(),