fix: dropdown and multiselect component values on disabled and option text not truncating (#3089)

* Fixed dropdown component showing empty value and not showing dropdown when combobox is true

* Fixed multiselect component showing empty value and not showing dropdown when combobox is true

* Added disabled onChange on multiline and dropdown, with snapshot ignore

* Fixed tooltip skip delay duration that made tooltip on Dropdown unusable

* Fixed size of text inside dropdown and multiselect

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
Lucas Oliveira 2024-07-30 18:30:50 -03:00 committed by GitHub
commit 1336ae0772
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 97 additions and 65 deletions

View file

@ -5,6 +5,7 @@ import { ChangeEvent, useEffect, useRef, useState } from "react";
import { DropDownComponentType } from "../../types/components";
import { cn } from "../../utils/utils";
import { default as ForwardedIconComponent } from "../genericIconComponent";
import ShadTooltip from "../shadTooltipComponent";
import { Button } from "../ui/button";
import {
Command,
@ -47,15 +48,21 @@ export default function Dropdown({
const value = event.target.value;
const searchValues = fuse.search(value);
const filtered = searchValues.map((search) => search.item);
if (!filtered.includes(value) && combobox) filtered.push(value);
if (!filtered.includes(value) && combobox && value) filtered.push(value);
setFilteredOptions(value ? filtered : options);
setCustomValue(value);
};
useEffect(() => {
if (disabled && value !== "") {
onSelect("", undefined, true);
}
}, [disabled]);
useEffect(() => {
if (open) {
const filtered = cloneDeep(options);
if (customValue === value && combobox) {
if (customValue === value && value && combobox) {
filtered.push(customValue);
}
setFilteredOptions(filtered);
@ -64,7 +71,7 @@ export default function Dropdown({
return (
<>
{Object.keys(options ?? [])?.length > 0 ? (
{Object.keys(options ?? [])?.length > 0 || combobox ? (
<>
<Popover open={open} onOpenChange={children ? () => {} : setOpen}>
{children ? (
@ -131,32 +138,40 @@ export default function Dropdown({
<CommandEmpty>No values found.</CommandEmpty>
<CommandGroup defaultChecked={false}>
{filteredOptions?.map((option, id) => (
<CommandItem
<ShadTooltip
delayDuration={700}
key={id}
value={option}
onSelect={(currentValue) => {
onSelect(currentValue);
setOpen(false);
}}
className="items-center truncate"
data-testid={`${option}-${id ?? ""}-option`}
content={option}
>
{customValue === option ? (
<span className="text-muted-foreground">
Text:&nbsp;
</span>
) : (
<></>
)}
{option}
<ForwardedIconComponent
name="Check"
className={cn(
"ml-auto h-4 w-4 text-primary",
value === option ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
<div>
<CommandItem
key={id}
value={option}
onSelect={(currentValue) => {
onSelect(currentValue);
setOpen(false);
}}
className="items-center overflow-hidden truncate"
data-testid={`${option}-${id ?? ""}-option`}
>
{customValue === option ? (
<span className="text-muted-foreground">
Text:&nbsp;
</span>
) : (
<></>
)}
<span className="truncate">{option}</span>
<ForwardedIconComponent
name="Check"
className={cn(
"ml-auto h-4 w-4 shrink-0 text-primary",
value === option ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
</div>
</ShadTooltip>
))}
</CommandGroup>
</CommandList>

View file

@ -18,7 +18,7 @@ export default function InputListComponent({
}: InputListComponentType): JSX.Element {
useEffect(() => {
if (disabled && value.length > 0 && value[0] !== "") {
onChange([""]);
onChange([""], undefined, true);
}
}, [disabled]);

View file

@ -4,6 +4,7 @@ import { useEffect, useRef, useState } from "react";
import { MultiselectComponentType } from "../../types/components";
import { cn } from "../../utils/utils";
import { default as ForwardedIconComponent } from "../genericIconComponent";
import ShadTooltip from "../shadTooltipComponent";
import { Button } from "../ui/button";
import {
Command,
@ -51,7 +52,7 @@ export default function MultiselectComponent({
const fuse = onlySelected ? fuseValues : fuseOptions;
const searchValues = fuse.search(v);
let filtered: string[] = searchValues.map((search) => search.item);
if (!filtered.includes(v) && combobox) filtered = [v, ...filtered];
if (!filtered.includes(v) && combobox && v) filtered = [v, ...filtered];
setFilteredOptions(
v
? filtered
@ -61,6 +62,12 @@ export default function MultiselectComponent({
);
};
useEffect(() => {
if (disabled && value.length > 0 && value[0] !== "") {
onSelect([], undefined, true);
}
}, [disabled]);
useEffect(() => {
searchRoleByTerm(searchValue);
}, [onlySelected]);
@ -72,7 +79,7 @@ export default function MultiselectComponent({
useEffect(() => {
setCustomValues(value.filter((v) => !defaultOptions.includes(v)) ?? []);
setOptions([
...value.filter((v) => !defaultOptions.includes(v)),
...value.filter((v) => !defaultOptions.includes(v) && v),
...defaultOptions,
]);
}, [value]);
@ -87,7 +94,7 @@ export default function MultiselectComponent({
return (
<>
{Object.keys(options ?? [])?.length > 0 ? (
{Object.keys(options ?? [])?.length > 0 || combobox ? (
<>
<Popover open={open} onOpenChange={children ? () => {} : setOpen}>
{children ? (
@ -171,38 +178,48 @@ export default function MultiselectComponent({
<CommandEmpty>No values found.</CommandEmpty>
<CommandGroup defaultChecked={false}>
{filteredOptions?.map((option, id) => (
<CommandItem
<ShadTooltip
delayDuration={700}
key={id}
value={option}
onSelect={(currentValue) => {
if (value.includes(currentValue)) {
onSelect(value.filter((v) => v !== currentValue));
} else {
onSelect([...value, currentValue]);
}
}}
className="items-center truncate"
data-testid={`${option}-${id ?? ""}-option`}
content={option}
>
{customValues.includes(option) ||
searchValue === option ? (
<span className="text-muted-foreground">
Text:&nbsp;
</span>
) : (
<></>
)}
{option}
<ForwardedIconComponent
name="Check"
className={cn(
"ml-auto h-4 w-4 text-primary",
value.includes(option)
? "opacity-100"
: "opacity-0",
)}
/>
</CommandItem>
<div>
<CommandItem
key={id}
value={option}
onSelect={(currentValue) => {
if (value.includes(currentValue)) {
onSelect(
value.filter((v) => v !== currentValue),
);
} else {
onSelect([...value, currentValue]);
}
}}
className="items-center overflow-hidden truncate"
data-testid={`${option}-${id ?? ""}-option`}
>
{customValues.includes(option) ||
searchValue === option ? (
<span className="text-muted-foreground">
Text:&nbsp;
</span>
) : (
<></>
)}
<span className="truncate">{option}</span>
<ForwardedIconComponent
name="Check"
className={cn(
"ml-auto h-4 w-4 shrink-0 text-primary",
value.includes(option)
? "opacity-100"
: "opacity-0",
)}
/>
</CommandItem>
</div>
</ShadTooltip>
))}
</CommandGroup>
</CommandList>

View file

@ -14,7 +14,7 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<AuthProvider>
<TooltipProvider>
<TooltipProvider skipDelayDuration={0}>
<ReactFlowProvider>
<ApiInterceptor />
{children}

View file

@ -56,7 +56,7 @@ export type DropDownComponentType = {
value: string;
combobox?: boolean;
options: string[];
onSelect: (value: string) => void;
onSelect: (value: string, dbValue?: boolean, snapshot?: boolean) => void;
editNode?: boolean;
id?: string;
children?: ReactNode;
@ -67,7 +67,7 @@ export type MultiselectComponentType = {
value: string[];
combobox?: boolean;
options: string[];
onSelect: (value: string[]) => void;
onSelect: (value: string[], dbValue?: boolean, snapshot?: boolean) => void;
editNode?: boolean;
id?: string;
children?: ReactNode;
@ -96,7 +96,7 @@ export type ParameterComponentType = {
};
export type InputListComponentType = {
value: string[];
onChange: (value: string[]) => void;
onChange: (value: string[], dbValue?: boolean, snapshot?: boolean) => void;
disabled: boolean;
editNode?: boolean;
componentName?: string;