From ce738df0c15689ae20e73f9cccf61d5c04962e4c Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 20 Mar 2025 11:56:40 -0600 Subject: [PATCH] tag input is updated --- .../features/modal/InvitePeopleModal.tsx | 19 ++++++++------ .../ui/inputs/InputTagInput.stories.tsx | 14 +++++----- .../components/ui/inputs/InputTagInput.tsx | 15 +++++------ .../BusterInfiniteList/BusterInfiniteList.tsx | 26 ------------------- web/src/components/ui/list/EmptyStateList.tsx | 2 -- web/src/components/ui/select/SelectBase.tsx | 2 +- .../PermissionListUsersContainer.tsx | 4 +-- .../PermissionUsersSelectedPopup.tsx | 6 ++--- .../DatasetPermissionUser/config.ts | 6 ++--- 9 files changed, 34 insertions(+), 60 deletions(-) diff --git a/web/src/components/features/modal/InvitePeopleModal.tsx b/web/src/components/features/modal/InvitePeopleModal.tsx index df834c5f0..e0284ec81 100644 --- a/web/src/components/features/modal/InvitePeopleModal.tsx +++ b/web/src/components/features/modal/InvitePeopleModal.tsx @@ -1,8 +1,10 @@ import React, { useMemo } from 'react'; import { useMemoizedFn } from '@/hooks'; import { AppModal } from '@/components/ui/modal'; -import { TagInput } from '@/components/ui/inputs/InputTagInput'; +import { InputTagInput } from '@/components/ui/inputs/InputTagInput'; import { useInviteUser } from '@/api/buster_rest/users'; +import { validate } from 'email-validator'; +import { useBusterNotifications } from '@/context/BusterNotifications'; export const InvitePeopleModal: React.FC<{ open: boolean; @@ -10,16 +12,13 @@ export const InvitePeopleModal: React.FC<{ }> = React.memo(({ open, onClose }) => { const [emails, setEmails] = React.useState([]); const { mutateAsync: inviteUsers, isPending: inviting } = useInviteUser(); + const { openErrorMessage } = useBusterNotifications(); const handleInvite = useMemoizedFn(async () => { await inviteUsers({ emails }); onClose(); }); - const onCloseEmail = useMemoizedFn((email: string) => { - setEmails(emails.filter((e) => e !== email)); - }); - const memoizedHeader = useMemo(() => { return { title: 'Invite others to join your workspace', @@ -41,10 +40,14 @@ export const InvitePeopleModal: React.FC<{ return (
- { - setEmails([...emails, v]); + if (validate(v)) { + setEmails([...emails, v]); + } else { + openErrorMessage(`Invalid email - ${v}`); + } }} onTagRemove={(index) => { setEmails(emails.filter((_, i) => i !== index)); diff --git a/web/src/components/ui/inputs/InputTagInput.stories.tsx b/web/src/components/ui/inputs/InputTagInput.stories.tsx index 260bc5d4f..8b82b961c 100644 --- a/web/src/components/ui/inputs/InputTagInput.stories.tsx +++ b/web/src/components/ui/inputs/InputTagInput.stories.tsx @@ -1,13 +1,13 @@ 'use client'; import type { Meta, StoryObj } from '@storybook/react'; -import { TagInput } from './InputTagInput'; +import { InputTagInput } from './InputTagInput'; import { useState } from 'react'; import React from 'react'; -const meta: Meta = { +const meta: Meta = { title: 'UI/Inputs/InputTagInput', - component: TagInput, + component: InputTagInput, tags: ['autodocs'], argTypes: { variant: { @@ -31,10 +31,10 @@ const meta: Meta = { }; export default meta; -type Story = StoryObj; +type Story = StoryObj; // Interactive component for Storybook -const InteractiveTagInput = (args: React.ComponentProps) => { +const InteractiveTagInput = (args: React.ComponentProps) => { const [tags, setTags] = useState(args.tags || []); const handleTagAdd = (tag: string) => { @@ -47,7 +47,9 @@ const InteractiveTagInput = (args: React.ComponentProps) => { setTags(newTags); }; - return ; + return ( + + ); }; export const Default: Story = { diff --git a/web/src/components/ui/inputs/InputTagInput.tsx b/web/src/components/ui/inputs/InputTagInput.tsx index 29c676d22..d1e679793 100644 --- a/web/src/components/ui/inputs/InputTagInput.tsx +++ b/web/src/components/ui/inputs/InputTagInput.tsx @@ -7,18 +7,17 @@ import { useMemoizedFn } from '@/hooks'; import { inputVariants } from './Input'; import { InputTag } from './InputTag'; -export interface TagInputProps - extends Omit, 'size'>, - VariantProps { - tags?: string[]; +export interface TagInputProps extends VariantProps { + tags: string[]; onTagAdd?: (tag: string) => void; onTagRemove?: (index: number) => void; placeholder?: string; disabled?: boolean; maxTags?: number; + className?: string; } -const TagInput = React.forwardRef( +const InputTagInput = React.forwardRef( ( { className, @@ -116,6 +115,7 @@ const TagInput = React.forwardRef( ))} ( className="placeholder:text-gray-light min-w-[120px] flex-1 bg-transparent outline-none disabled:cursor-not-allowed disabled:opacity-50" placeholder={tags.length === 0 ? placeholder : undefined} disabled={isDisabledInput} - {...props} />
); } ); -TagInput.displayName = 'TagInput'; +InputTagInput.displayName = 'TagInput'; -export { TagInput }; +export { InputTagInput }; diff --git a/web/src/components/ui/list/BusterInfiniteList/BusterInfiniteList.tsx b/web/src/components/ui/list/BusterInfiniteList/BusterInfiniteList.tsx index 5d9eb41a8..57cd33ddb 100644 --- a/web/src/components/ui/list/BusterInfiniteList/BusterInfiniteList.tsx +++ b/web/src/components/ui/list/BusterInfiniteList/BusterInfiniteList.tsx @@ -135,32 +135,6 @@ export const BusterInfiniteList: React.FC = React.memo( return () => scrollableParent.removeEventListener('scroll', handleScroll); }, [onScrollEnd, scrollEndThreshold]); - useWhyDidYouUpdate('BusterInfiniteList', { - columns, - rows, - selectedRowKeys, - onSelectChange, - emptyState, - contextMenu, - hideLastRowBorder, - showSelectAll, - onScrollEnd, - loadingNewContent, - rowClassName, - scrollEndThreshold, - useRowClickSelectChange, - showHeader, - itemData, - globalCheckStatus, - lastChildIndex, - showEmptyState, - containerRef, - scrollRef, - onGlobalSelectChange, - onSelectSectionChange, - onSelectChangePreflight - }); - return (
{showHeader && !showEmptyState && ( diff --git a/web/src/components/ui/list/EmptyStateList.tsx b/web/src/components/ui/list/EmptyStateList.tsx index 6152ee711..1a3dad21b 100644 --- a/web/src/components/ui/list/EmptyStateList.tsx +++ b/web/src/components/ui/list/EmptyStateList.tsx @@ -10,8 +10,6 @@ interface EmptyStateListProps { export const EmptyStateList = React.memo( ({ show = true, text, variant = 'default' }: EmptyStateListProps) => { - console.log('hit!', show, text, variant); - if (!show) return null; if (variant === 'card') { diff --git a/web/src/components/ui/select/SelectBase.tsx b/web/src/components/ui/select/SelectBase.tsx index 6ac204c4a..c059e02c9 100644 --- a/web/src/components/ui/select/SelectBase.tsx +++ b/web/src/components/ui/select/SelectBase.tsx @@ -13,7 +13,7 @@ const SelectGroup = SelectPrimitive.Group; const SelectValue = SelectPrimitive.Value; export const selectVariants = cva( - 'flex w-full gap-x-1.5 transition-colors transition-border duration-200 items-center justify-between rounded border px-3 py-1 text-sm focus:outline-none cursor-pointer disabled:cursor-not-allowed disabled:opacity-60 [&>span]:line-clamp-1', + 'flex w-full gap-x-1.5 transition-colors transition-border text-foreground duration-200 items-center justify-between rounded border px-3 py-1 text-sm focus:outline-none cursor-pointer disabled:cursor-not-allowed disabled:opacity-60 [&>span]:line-clamp-1', { variants: { variant: { diff --git a/web/src/controllers/DatasetPermissionUser/PermissionListUsersContainer.tsx b/web/src/controllers/DatasetPermissionUser/PermissionListUsersContainer.tsx index 4a6bb998b..1b2a2bd37 100644 --- a/web/src/controllers/DatasetPermissionUser/PermissionListUsersContainer.tsx +++ b/web/src/controllers/DatasetPermissionUser/PermissionListUsersContainer.tsx @@ -157,9 +157,9 @@ const PermissionGroupAssignedCell: React.FC<{
e.stopPropagation()}>