From c8250c02629179e7f9ba63b0a7c4b8874bfd5d13 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 19 Jun 2026 23:12:26 +0100 Subject: [PATCH] feat(base): generate choice ids as nanoid on the client --- apps/client/package.json | 1 + .../src/ee/base/components/cells/cell-multi-select.tsx | 4 ++-- .../src/ee/base/components/cells/cell-select.tsx | 4 ++-- .../src/ee/base/components/cells/choice-picker.tsx | 4 ++-- .../src/ee/base/components/property/choice-editor.tsx | 10 +++++----- apps/client/src/ee/base/utils/generate-base-id.ts | 5 +++++ pnpm-lock.yaml | 3 +++ 7 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 apps/client/src/ee/base/utils/generate-base-id.ts diff --git a/apps/client/package.json b/apps/client/package.json index 86b20d9d0..02ba26af5 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -51,6 +51,7 @@ "lowlight": "3.3.0", "mantine-form-zod-resolver": "1.3.0", "mermaid": "11.15.0", + "nanoid": "^3.3.8", "mitt": "3.0.1", "posthog-js": "1.372.2", "react": "18.3.1", diff --git a/apps/client/src/ee/base/components/cells/cell-multi-select.tsx b/apps/client/src/ee/base/components/cells/cell-multi-select.tsx index cef57aa09..5f473c2d6 100644 --- a/apps/client/src/ee/base/components/cells/cell-multi-select.tsx +++ b/apps/client/src/ee/base/components/cells/cell-multi-select.tsx @@ -16,7 +16,7 @@ import { import { choiceColor } from "@/ee/base/components/cells/choice-color"; import { BadgeOverflowList } from "@/ee/base/components/cells/badge-overflow"; import { useUpdatePropertyMutation } from "@/ee/base/queries/base-property-query"; -import { v7 as uuid7 } from "uuid"; +import { generateBaseChoiceId } from "@/ee/base/utils/generate-base-id"; import cellClasses from "@/ee/base/styles/cells.module.css"; import { useListKeyboardNav } from "@/ee/base/hooks/use-list-keyboard-nav"; @@ -109,7 +109,7 @@ export function CellMultiSelect({ const handleAddOption = useCallback(() => { if (!trimmedSearch) return; const newChoice: Choice = { - id: uuid7(), + id: generateBaseChoiceId(), name: trimmedSearch, color: addOptionColor, }; diff --git a/apps/client/src/ee/base/components/cells/cell-select.tsx b/apps/client/src/ee/base/components/cells/cell-select.tsx index 8cc9bca08..1e346a496 100644 --- a/apps/client/src/ee/base/components/cells/cell-select.tsx +++ b/apps/client/src/ee/base/components/cells/cell-select.tsx @@ -9,7 +9,7 @@ import { import { choiceColor } from "@/ee/base/components/cells/choice-color"; import { ChoiceBadge } from "@/ee/base/components/cells/choice-badge"; import { useUpdatePropertyMutation } from "@/ee/base/queries/base-property-query"; -import { v7 as uuid7 } from "uuid"; +import { generateBaseChoiceId } from "@/ee/base/utils/generate-base-id"; import cellClasses from "@/ee/base/styles/cells.module.css"; import { useListKeyboardNav } from "@/ee/base/hooks/use-list-keyboard-nav"; @@ -96,7 +96,7 @@ export function CellSelect({ const handleAddOption = useCallback(() => { if (!trimmedSearch) return; const newChoice: Choice = { - id: uuid7(), + id: generateBaseChoiceId(), name: trimmedSearch, color: addOptionColor, }; diff --git a/apps/client/src/ee/base/components/cells/choice-picker.tsx b/apps/client/src/ee/base/components/cells/choice-picker.tsx index e7d0c83ca..cdc8b9414 100644 --- a/apps/client/src/ee/base/components/cells/choice-picker.tsx +++ b/apps/client/src/ee/base/components/cells/choice-picker.tsx @@ -9,7 +9,7 @@ import { } from "@/ee/base/types/base.types"; import { choiceColor } from "@/ee/base/components/cells/choice-color"; import { useUpdatePropertyMutation } from "@/ee/base/queries/base-property-query"; -import { v7 as uuid7 } from "uuid"; +import { generateBaseChoiceId } from "@/ee/base/utils/generate-base-id"; import { useListKeyboardNav } from "@/ee/base/hooks/use-list-keyboard-nav"; import cellClasses from "@/ee/base/styles/cells.module.css"; @@ -124,7 +124,7 @@ export function ChoicePicker({ const handleAddOption = useCallback(() => { if (!trimmedSearch) return; const newChoice: Choice = { - id: uuid7(), + id: generateBaseChoiceId(), name: trimmedSearch, color: addOptionColor, }; diff --git a/apps/client/src/ee/base/components/property/choice-editor.tsx b/apps/client/src/ee/base/components/property/choice-editor.tsx index f019baec7..fc16a7a34 100644 --- a/apps/client/src/ee/base/components/property/choice-editor.tsx +++ b/apps/client/src/ee/base/components/property/choice-editor.tsx @@ -35,7 +35,7 @@ import { BaseDropEdgeIndicator } from "@/ee/base/components/grid/base-drop-edge- import { Choice } from "@/ee/base/types/base.types"; import { choiceColor } from "@/ee/base/components/cells/choice-color"; import { useTranslation } from "react-i18next"; -import { v7 as uuid7 } from "uuid"; +import { generateBaseChoiceId } from "@/ee/base/utils/generate-base-id"; import { DefaultValuePicker } from "./default-value-picker"; const CHOICE_COLORS = [ @@ -52,9 +52,9 @@ const STATUS_CATEGORIES = [ // Default choices for a new status property, one per category. export function defaultStatusChoices(): Choice[] { return [ - { id: uuid7(), name: "Not started", color: "gray", category: "todo" }, - { id: uuid7(), name: "In progress", color: "blue", category: "inProgress" }, - { id: uuid7(), name: "Done", color: "green", category: "complete" }, + { id: generateBaseChoiceId(), name: "Not started", color: "gray", category: "todo" }, + { id: generateBaseChoiceId(), name: "In progress", color: "blue", category: "inProgress" }, + { id: generateBaseChoiceId(), name: "Done", color: "green", category: "complete" }, ]; } @@ -169,7 +169,7 @@ export function ChoiceEditor({ }, []); const handleAdd = useCallback((category?: "todo" | "inProgress" | "complete") => { - const id = uuid7(); + const id = generateBaseChoiceId(); setDraft((prev) => { const colorIndex = prev.length % CHOICE_COLORS.length; const newChoice: Choice = { diff --git a/apps/client/src/ee/base/utils/generate-base-id.ts b/apps/client/src/ee/base/utils/generate-base-id.ts new file mode 100644 index 000000000..0316f74ba --- /dev/null +++ b/apps/client/src/ee/base/utils/generate-base-id.ts @@ -0,0 +1,5 @@ +import { customAlphabet } from "nanoid"; + +const baseIdSuffix = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 9); + +export const generateBaseChoiceId = (): string => `opt${baseIdSuffix()}`; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f531fe0af..71a6ea3db 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -368,6 +368,9 @@ importers: mitt: specifier: 3.0.1 version: 3.0.1 + nanoid: + specifier: 3.3.8 + version: 3.3.8 posthog-js: specifier: 1.372.2 version: 1.372.2