feat: add loading state to regenerate and generate buttons in JSON schema generator

This commit is contained in:
twwu 2025-03-27 11:39:20 +08:00
parent e5e9ab0adb
commit b52a0d6fa5
4 changed files with 44 additions and 31 deletions

View File

@ -9,6 +9,7 @@ import { getValidationErrorMessage, validateSchemaAgainstDraft7 } from '../../..
type GeneratedResultProps = {
schema: SchemaRoot
isGenerating: boolean
onBack: () => void
onRegenerate: () => void
onClose: () => void
@ -17,6 +18,7 @@ type GeneratedResultProps = {
const GeneratedResult: FC<GeneratedResultProps> = ({
schema,
isGenerating,
onBack,
onRegenerate,
onClose,
@ -87,7 +89,13 @@ const GeneratedResult: FC<GeneratedResultProps> = ({
<span>{t('workflow.nodes.llm.jsonSchema.back')}</span>
</Button>
<div className='flex items-center gap-x-2'>
<Button variant='secondary' className='flex items-center gap-x-0.5' onClick={onRegenerate}>
<Button
variant='secondary'
className='flex items-center gap-x-0.5'
onClick={onRegenerate}
disabled={isGenerating}
loading={isGenerating}
>
<RiSparklingLine className='h-4 w-4' />
<span>{t('workflow.nodes.llm.jsonSchema.regenerate')}</span>
</Button>

View File

@ -97,7 +97,7 @@ export const JsonSchemaGenerator: FC<JsonSchemaGeneratorProps> = ({
)
}, [])
const { mutateAsync: generateStructuredOutputRules } = useGenerateStructuredOutputRules()
const { mutateAsync: generateStructuredOutputRules, isPending: isGenerating } = useGenerateStructuredOutputRules()
const generateSchema = useCallback(async () => {
const { output, error } = await generateStructuredOutputRules({ instruction, model_config: model! })
@ -159,6 +159,7 @@ export const JsonSchemaGenerator: FC<JsonSchemaGeneratorProps> = ({
<PromptEditor
instruction={instruction}
model={model}
isGenerating={isGenerating}
onInstructionChange={setInstruction}
onCompletionParamsChange={handleCompletionParamsChange}
onGenerate={handleGenerate}
@ -169,6 +170,7 @@ export const JsonSchemaGenerator: FC<JsonSchemaGeneratorProps> = ({
{view === GeneratorView.result && (
<GeneratedResult
schema={schema!}
isGenerating={isGenerating}
onBack={goBackToPromptEditor}
onRegenerate={handleRegenerate}
onApply={handleApply}

View File

@ -19,6 +19,7 @@ export type ModelInfo = {
type PromptEditorProps = {
instruction: string
model: Model
isGenerating: boolean
onInstructionChange: (instruction: string) => void
onCompletionParamsChange: (newParams: FormValue) => void
onModelChange: (model: ModelInfo) => void
@ -29,6 +30,7 @@ type PromptEditorProps = {
const PromptEditor: FC<PromptEditorProps> = ({
instruction,
model,
isGenerating,
onInstructionChange,
onCompletionParamsChange,
onClose,
@ -96,6 +98,8 @@ const PromptEditor: FC<PromptEditorProps> = ({
variant='primary'
className='flex items-center gap-x-0.5'
onClick={onGenerate}
disabled={isGenerating}
loading={isGenerating}
>
<RiSparklingFill className='h-4 w-4' />
<span>{t('workflow.nodes.llm.jsonSchema.generate')}</span>

View File

@ -1,5 +1,4 @@
import React, { type FC, useCallback, useState } from 'react'
import { RiArrowDownDoubleLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
import Textarea from '@/app/components/base/textarea'
@ -18,7 +17,7 @@ const AdvancedOptions: FC<AdvancedOptionsProps> = ({
options,
}) => {
const { t } = useTranslation()
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false)
// const [showAdvancedOptions, setShowAdvancedOptions] = useState(false)
const [enumValue, setEnumValue] = useState(options.enum)
const handleEnumChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
@ -29,37 +28,37 @@ const AdvancedOptions: FC<AdvancedOptionsProps> = ({
onChange({ enum: e.target.value })
}, [onChange])
const handleToggleAdvancedOptions = useCallback(() => {
setShowAdvancedOptions(prev => !prev)
}, [])
// const handleToggleAdvancedOptions = useCallback(() => {
// setShowAdvancedOptions(prev => !prev)
// }, [])
return (
<div className='border-t border-divider-subtle'>
{showAdvancedOptions ? (
<div className='flex flex-col gap-y-1 px-2 py-1.5'>
<div className='flex w-full items-center gap-x-2'>
<span className='system-2xs-medium-uppercase text-text-tertiary'>
{t('workflow.nodes.llm.jsonSchema.stringValidations')}
</span>
<div className='grow'>
<Divider type='horizontal' className='my-0 h-px bg-line-divider-bg' />
</div>
</div>
<div className='flex flex-col'>
<div className='system-xs-medium flex h-6 items-center text-text-secondary'>
Enum
</div>
<Textarea
size='small'
className='min-h-6'
value={enumValue}
onChange={handleEnumChange}
onBlur={handleEnumBlur}
placeholder={'abcd, 1, 1.5, etc.'}
/>
{/* {showAdvancedOptions ? ( */}
<div className='flex flex-col gap-y-1 px-2 py-1.5'>
<div className='flex w-full items-center gap-x-2'>
<span className='system-2xs-medium-uppercase text-text-tertiary'>
{t('workflow.nodes.llm.jsonSchema.stringValidations')}
</span>
<div className='grow'>
<Divider type='horizontal' className='my-0 h-px bg-line-divider-bg' />
</div>
</div>
) : (
<div className='flex flex-col'>
<div className='system-xs-medium flex h-6 items-center text-text-secondary'>
Enum
</div>
<Textarea
size='small'
className='min-h-6'
value={enumValue}
onChange={handleEnumChange}
onBlur={handleEnumBlur}
placeholder={'abcd, 1, 1.5, etc.'}
/>
</div>
</div>
{/* ) : (
<button
type='button'
className='flex items-center gap-x-0.5 pb-1 pl-1.5 pr-2 pt-2'
@ -70,7 +69,7 @@ const AdvancedOptions: FC<AdvancedOptionsProps> = ({
{t('workflow.nodes.llm.jsonSchema.showAdvancedOptions')}
</span>
</button>
)}
)} */}
</div>
)
}