Browse Source

feat: make default slider behavior better (#1988)

crazywoola 1 year ago
parent
commit
3f25e7ec79

+ 109 - 120
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx

@@ -12,6 +12,7 @@ import { SimpleSelect } from '@/app/components/base/select'
 import TagInput from '@/app/components/base/tag-input'
 
 export type ParameterValue = number | string | string[] | boolean | undefined
+
 type ParameterItemProps = {
   parameterRule: ModelParameterRule
   value?: ParameterValue
@@ -28,48 +29,29 @@ const ParameterItem: FC<ParameterItemProps> = ({
 }) => {
   const language = useLanguage()
   const [localValue, setLocalValue] = useState(value)
-  const mergedValue = isNullOrUndefined(value) ? localValue : value
 
   const getDefaultValue = () => {
     let defaultValue: ParameterValue
 
-    if (parameterRule.type === 'int' || parameterRule.type === 'float') {
-      if (isNullOrUndefined(parameterRule.default)) {
-        if (parameterRule.min)
-          defaultValue = parameterRule.min
-        else
-          defaultValue = 0
-      }
-      else {
-        defaultValue = parameterRule.default
-      }
-    }
-
-    if (parameterRule.type === 'string' && !parameterRule.options?.length)
-      defaultValue = parameterRule.default || ''
-
-    if (parameterRule.type === 'string' && parameterRule.options?.length)
-      defaultValue = parameterRule.default || ''
-
-    if (parameterRule.type === 'boolean')
+    if (parameterRule.type === 'int' || parameterRule.type === 'float')
+      defaultValue = isNullOrUndefined(parameterRule.default) ? (parameterRule.min || 0) : parameterRule.default
+    else if (parameterRule.type === 'string')
+      defaultValue = parameterRule.options?.length ? (parameterRule.default || '') : (parameterRule.default || '')
+    else if (parameterRule.type === 'boolean')
       defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : false
-
-    if (parameterRule.type === 'tag')
+    else if (parameterRule.type === 'tag')
       defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : []
 
     return defaultValue
   }
-  const renderValue = isNullOrUndefined(mergedValue) ? getDefaultValue() : mergedValue
 
-  const handleChange = (v: ParameterValue) => {
-    setLocalValue(v)
+  const renderValue = value ?? localValue ?? getDefaultValue()
 
-    if (onChange) {
-      if (parameterRule.name === 'stop')
-        onChange(v)
-      else if (!isNullOrUndefined(value))
-        onChange(v)
-    }
+  const handleInputChange = (newValue: ParameterValue) => {
+    setLocalValue(newValue)
+
+    if (onChange && (parameterRule.name === 'stop' || !isNullOrUndefined(value)))
+      onChange(newValue)
   }
 
   const handleNumberInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -81,45 +63,127 @@ const ParameterItem: FC<ParameterItemProps> = ({
     if (!isNullOrUndefined(parameterRule.min) && num < parameterRule.min!)
       num = parameterRule.min as number
 
-    handleChange(num)
+    handleInputChange(num)
   }
 
   const handleSlideChange = (num: number) => {
-    handleChange(num)
+    handleInputChange(num)
   }
 
   const handleRadioChange = (v: number) => {
-    handleChange(v === 1)
+    handleInputChange(v === 1)
   }
 
   const handleStringInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    handleChange(e.target.value)
+    handleInputChange(e.target.value)
   }
 
   const handleSelect = (option: { value: string | number; name: string }) => {
-    handleChange(option.value)
+    handleInputChange(option.value)
   }
 
   const handleTagChange = (newSequences: string[]) => {
-    handleChange(newSequences)
+    handleInputChange(newSequences)
   }
 
   const handleSwitch = (checked: boolean) => {
     if (onSwitch) {
-      let assignValue: ParameterValue = localValue
-
-      if (isNullOrUndefined(localValue))
-        assignValue = getDefaultValue()
+      const assignValue: ParameterValue = localValue || getDefaultValue()
 
       onSwitch(checked, assignValue)
     }
   }
 
-  const numberInputWithSlide = (parameterRule.type === 'int' || parameterRule.type === 'float')
+  const renderInput = () => {
+    const numberInputWithSlide = (parameterRule.type === 'int' || parameterRule.type === 'float')
     && !isNullOrUndefined(parameterRule.min)
     && !isNullOrUndefined(parameterRule.max)
-  const numberInput = (parameterRule.type === 'int' || parameterRule.type === 'float')
-    && (isNullOrUndefined(parameterRule.min) || isNullOrUndefined(parameterRule.max))
+
+    if (parameterRule.type === 'int' || parameterRule.type === 'float') {
+      let step = 100
+      if (parameterRule.max) {
+        if (parameterRule.max < 10)
+          step = 0.1
+        else if (parameterRule.max < 100)
+          step = 1
+        else if (parameterRule.max < 1000)
+          step = 10
+        else if (parameterRule.max < 10000)
+          step = 100
+      }
+
+      return (
+        <>
+          {numberInputWithSlide && <Slider
+            className='w-[120px]'
+            value={renderValue as number}
+            min={parameterRule.min}
+            max={parameterRule.max}
+            step={step}
+            onChange={handleSlideChange}
+          />}
+          <input
+            className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
+            type='number'
+            max={parameterRule.max}
+            min={parameterRule.min}
+            step={numberInputWithSlide ? step : +`0.${parameterRule.precision || 0}`}
+            value={renderValue as string}
+            onChange={handleNumberInputChange}
+          />
+        </>
+      )
+    }
+
+    if (parameterRule.type === 'boolean') {
+      return (
+        <Radio.Group
+          className='w-[200px] flex items-center'
+          value={renderValue ? 1 : 0}
+          onChange={handleRadioChange}
+        >
+          <Radio value={1} className='!mr-1 w-[94px]'>True</Radio>
+          <Radio value={0} className='w-[94px]'>False</Radio>
+        </Radio.Group>
+      )
+    }
+
+    if (parameterRule.type === 'string' && !parameterRule.options?.length) {
+      return (
+        <input
+          className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
+          value={renderValue as string}
+          onChange={handleStringInputChange}
+        />
+      )
+    }
+
+    if (parameterRule.type === 'string' && !!parameterRule?.options?.length) {
+      return (
+        <SimpleSelect
+          className='!py-0'
+          wrapperClassName='!w-[200px] !h-8'
+          defaultValue={renderValue as string}
+          onSelect={handleSelect}
+          items={parameterRule.options.map(option => ({ value: option, name: option }))}
+        />
+      )
+    }
+
+    if (parameterRule.type === 'tag') {
+      return (
+        <div className='w-[200px]'>
+          <TagInput
+            items={renderValue as string[]}
+            onChange={handleTagChange}
+            customizedConfirmKey='Tab'
+          />
+        </div>
+      )
+    }
+
+    return null
+  }
 
   return (
     <div className={`flex items-center justify-between ${className}`}>
@@ -161,82 +225,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
           )
         }
       </div>
-      {
-        numberInputWithSlide && (
-          <div className='flex items-center'>
-            <Slider
-              className='w-[120px]'
-              value={renderValue as number}
-              min={parameterRule.min}
-              max={parameterRule.max}
-              step={+`0.${parameterRule.precision || 0}`}
-              onChange={handleSlideChange}
-            />
-            <input
-              className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
-              type='number'
-              max={parameterRule.max}
-              min={parameterRule.min}
-              step={+`0.${parameterRule.precision || 0}`}
-              value={renderValue as string}
-              onChange={handleNumberInputChange}
-            />
-          </div>
-        )
-      }
-      {
-        parameterRule.type === 'boolean' && (
-          <Radio.Group
-            className='w-[200px] flex items-center'
-            value={renderValue ? 1 : 0}
-            onChange={handleRadioChange}
-          >
-            <Radio value={1} className='!mr-1 w-[94px]'>True</Radio>
-            <Radio value={0} className='w-[94px]'>False</Radio>
-          </Radio.Group>
-        )
-      }
-      {
-        numberInput && (
-          <input
-            type='number'
-            className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
-            value={renderValue as string}
-            onChange={handleNumberInputChange}
-          />
-        )
-      }
-      {
-        parameterRule.type === 'string' && !parameterRule.options?.length && (
-          <input
-            className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
-            value={renderValue as string}
-            onChange={handleStringInputChange}
-          />
-        )
-      }
-      {
-        parameterRule.type === 'string' && !!parameterRule?.options?.length && (
-          <SimpleSelect
-            className='!py-0'
-            wrapperClassName='!w-[200px] !h-8'
-            defaultValue={renderValue as string}
-            onSelect={handleSelect}
-            items={parameterRule.options.map(option => ({ value: option, name: option }))}
-          />
-        )
-      }
-      {
-        parameterRule.type === 'tag' && (
-          <div className='w-[200px]'>
-            <TagInput
-              items={renderValue as string[]}
-              onChange={handleTagChange}
-              customizedConfirmKey='Tab'
-            />
-          </div>
-        )
-      }
+      {renderInput()}
     </div>
   )
 }