### What problem does this PR solve? Feat: The value selected in the Select component only displays the icon #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.1
| @@ -16,6 +16,7 @@ export default defineConfig({ | |||
| icons: {}, | |||
| hash: true, | |||
| favicons: ['/logo.svg'], | |||
| headScripts: [{ src: '/iconfont.js', defer: true }], | |||
| clickToComponent: {}, | |||
| history: { | |||
| type: 'browser', | |||
| @@ -134,17 +134,16 @@ const SelectItem = React.forwardRef< | |||
| <SelectPrimitive.Item | |||
| ref={ref} | |||
| className={cn( | |||
| 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', | |||
| 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', | |||
| className, | |||
| )} | |||
| {...props} | |||
| > | |||
| <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | |||
| <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center"> | |||
| <SelectPrimitive.ItemIndicator> | |||
| <Check className="h-4 w-4" /> | |||
| </SelectPrimitive.ItemIndicator> | |||
| </span> | |||
| <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText> | |||
| </SelectPrimitive.Item> | |||
| )); | |||
| @@ -179,6 +178,7 @@ export type RAGFlowSelectOptionType = { | |||
| label: React.ReactNode; | |||
| value: string; | |||
| disabled?: boolean; | |||
| icon?: React.ReactNode; | |||
| }; | |||
| export type RAGFlowSelectGroupOptionType = { | |||
| @@ -193,6 +193,7 @@ export type RAGFlowSelectProps = Partial<ControllerRenderProps> & { | |||
| placeholder?: React.ReactNode; | |||
| contentProps?: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>; | |||
| triggerClassName?: string; | |||
| onlyShowSelectedIcon?: boolean; | |||
| } & SelectPrimitive.SelectProps; | |||
| /** | |||
| @@ -225,6 +226,7 @@ export const RAGFlowSelect = forwardRef< | |||
| contentProps = {}, | |||
| defaultValue, | |||
| triggerClassName, | |||
| onlyShowSelectedIcon = false, | |||
| }, | |||
| ref, | |||
| ) { | |||
| @@ -257,6 +259,24 @@ export const RAGFlowSelect = forwardRef< | |||
| }); | |||
| }, [initialValue]); | |||
| // The value selected in the drop-down box only displays the icon | |||
| const label = React.useMemo(() => { | |||
| let nextOptions = options; | |||
| if (options.some((x) => !('value' in x))) { | |||
| nextOptions = (options as RAGFlowSelectGroupOptionType[]).reduce< | |||
| RAGFlowSelectOptionType[] | |||
| >((pre, cur) => { | |||
| return pre.concat(cur?.options ?? []); | |||
| }, []); | |||
| } | |||
| const option = (nextOptions as RAGFlowSelectOptionType[]).find( | |||
| (x) => x.value === value, | |||
| ); | |||
| return onlyShowSelectedIcon ? option?.icon : option?.label; | |||
| }, [onlyShowSelectedIcon, options, value]); | |||
| return ( | |||
| <Select onValueChange={handleChange} value={value} key={key}> | |||
| <FormControlWidget> | |||
| @@ -267,7 +287,7 @@ export const RAGFlowSelect = forwardRef< | |||
| ref={ref} | |||
| className={triggerClassName} | |||
| > | |||
| <SelectValue placeholder={placeholder} /> | |||
| <SelectValue placeholder={placeholder}>{label}</SelectValue> | |||
| </SelectTrigger> | |||
| </FormControlWidget> | |||
| <SelectContent {...contentProps}> | |||
| @@ -279,14 +299,17 @@ export const RAGFlowSelect = forwardRef< | |||
| key={o.value} | |||
| disabled={o.disabled} | |||
| > | |||
| {o.label} | |||
| <div className="flex items-center gap-1"> | |||
| {o.icon} | |||
| {o.label} | |||
| </div> | |||
| </SelectItem> | |||
| ); | |||
| } | |||
| return ( | |||
| <SelectGroup key={idx}> | |||
| <SelectLabel>{o.label}</SelectLabel> | |||
| <SelectLabel className="pl-2">{o.label}</SelectLabel> | |||
| {o.options.map((x) => ( | |||
| <SelectItem value={x.value} key={x.value} disabled={x.disabled}> | |||
| {x.label} | |||
| @@ -3003,18 +3003,18 @@ export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb', 'mssql'].map( | |||
| export const SwitchElseTo = 'end_cpn_id'; | |||
| export const SwitchOperatorOptions = [ | |||
| { value: '=', label: 'equal' }, | |||
| { value: '≠', label: 'notEqual' }, | |||
| { value: '>', label: 'gt' }, | |||
| { value: '≥', label: 'ge' }, | |||
| { value: '<', label: 'lt' }, | |||
| { value: '≤', label: 'le' }, | |||
| { value: 'contains', label: 'contains' }, | |||
| { value: 'not contains', label: 'notContains' }, | |||
| { value: 'start with', label: 'startWith' }, | |||
| { value: 'end with', label: 'endWith' }, | |||
| { value: 'empty', label: 'empty' }, | |||
| { value: 'not empty', label: 'notEmpty' }, | |||
| { value: '=', label: 'equal', icon: 'equal' }, | |||
| { value: '≠', label: 'notEqual', icon: 'not-equals' }, | |||
| { value: '>', label: 'gt', icon: 'Less' }, | |||
| { value: '≥', label: 'ge', icon: 'Greater-or-equal' }, | |||
| { value: '<', label: 'lt', icon: 'Less' }, | |||
| { value: '≤', label: 'le', icon: 'less-or-equal' }, | |||
| { value: 'contains', label: 'contains', icon: 'Contains' }, | |||
| { value: 'not contains', label: 'notContains', icon: 'not-contains' }, | |||
| { value: 'start with', label: 'startWith', icon: 'list-start' }, | |||
| { value: 'end with', label: 'endWith', icon: 'list-end' }, | |||
| // { value: 'empty', label: 'empty', icon: '' }, | |||
| // { value: 'not empty', label: 'notEmpty', icon: '' }, | |||
| ]; | |||
| export const SwitchLogicOperatorOptions = ['and', 'or']; | |||
| @@ -1,4 +1,5 @@ | |||
| import { FormContainer } from '@/components/form-container'; | |||
| import { IconFont } from '@/components/icon-font'; | |||
| import { BlockButton, Button } from '@/components/ui/button'; | |||
| import { Card, CardContent } from '@/components/ui/card'; | |||
| import { | |||
| @@ -9,8 +10,10 @@ import { | |||
| FormMessage, | |||
| } from '@/components/ui/form'; | |||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { Separator } from '@/components/ui/separator'; | |||
| import { Textarea } from '@/components/ui/textarea'; | |||
| import { ISwitchForm } from '@/interfaces/database/flow'; | |||
| import { cn } from '@/lib/utils'; | |||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { X } from 'lucide-react'; | |||
| import { useMemo } from 'react'; | |||
| @@ -49,6 +52,12 @@ function ConditionCards({ name: parentName, node }: ConditionCardsProps) { | |||
| const switchOperatorOptions = useMemo(() => { | |||
| return SwitchOperatorOptions.map((x) => ({ | |||
| value: x.value, | |||
| icon: ( | |||
| <IconFont | |||
| name={x.icon} | |||
| className={cn('size-4', { 'rotate-180': x.value === '>' })} | |||
| ></IconFont> | |||
| ), | |||
| label: t(`flow.switchOperatorOptions.${x.label}`), | |||
| })); | |||
| }, [t]); | |||
| @@ -66,7 +75,7 @@ function ConditionCards({ name: parentName, node }: ConditionCardsProps) { | |||
| return ( | |||
| <div key={field.id} className="flex"> | |||
| <Card className="bg-transparent border-input-border border flex-1"> | |||
| <section className="p-2 bg-background-card flex justify-between"> | |||
| <section className="p-2 bg-background-card flex justify-between items-center"> | |||
| <FormField | |||
| control={form.control} | |||
| name={`${name}.${index}.cpn_id`} | |||
| @@ -76,29 +85,34 @@ function ConditionCards({ name: parentName, node }: ConditionCardsProps) { | |||
| <RAGFlowSelect | |||
| {...field} | |||
| options={componentIdOptions} | |||
| triggerClassName="w-30 text-background-checked" | |||
| /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| <FormField | |||
| control={form.control} | |||
| name={`${name}.${index}.operator`} | |||
| render={({ field }) => ( | |||
| <FormItem> | |||
| <FormControl> | |||
| <RAGFlowSelect | |||
| {...field} | |||
| options={switchOperatorOptions} | |||
| triggerClassName="w-30" | |||
| placeholder={t('common.pleaseSelect')} | |||
| triggerClassName="w-30 text-background-checked bg-transparent border-none" | |||
| /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| <div className="flex items-center"> | |||
| <Separator orientation="vertical" className="h-2.5" /> | |||
| <FormField | |||
| control={form.control} | |||
| name={`${name}.${index}.operator`} | |||
| render={({ field }) => ( | |||
| <FormItem> | |||
| <FormControl> | |||
| <RAGFlowSelect | |||
| {...field} | |||
| options={switchOperatorOptions} | |||
| onlyShowSelectedIcon | |||
| triggerClassName="w-30 bg-transparent border-none" | |||
| /> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| )} | |||
| /> | |||
| </div> | |||
| </section> | |||
| <CardContent className="p-4 "> | |||
| <FormField | |||
| @@ -178,13 +192,6 @@ const SwitchForm = ({ node }: IOperatorForm) => { | |||
| return conditions?.filter((x) => !!x).map((x) => x?.to) ?? []; | |||
| }; | |||
| const switchOperatorOptions = useMemo(() => { | |||
| return SwitchOperatorOptions.map((x) => ({ | |||
| value: x.value, | |||
| label: t(`flow.switchOperatorOptions.${x.label}`), | |||
| })); | |||
| }, [t]); | |||
| const switchLogicOperatorOptions = useMemo(() => { | |||
| return SwitchLogicOperatorOptions.map((x) => ({ | |||
| value: x, | |||