mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-14 14:06:15 +08:00
feat: enhance JSON schema editor with keyboard shortcuts and additional properties validation
This commit is contained in:
parent
44be94d5b5
commit
86b1295efa
@ -1,6 +1,8 @@
|
|||||||
import React, { type FC } from 'react'
|
import React, { type FC } from 'react'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
|
||||||
|
import { useKeyPress } from 'ahooks'
|
||||||
|
|
||||||
type AdvancedActionsProps = {
|
type AdvancedActionsProps = {
|
||||||
isConfirmDisabled: boolean
|
isConfirmDisabled: boolean
|
||||||
@ -8,6 +10,15 @@ type AdvancedActionsProps = {
|
|||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Key = (props: { keyName: string }) => {
|
||||||
|
const { keyName } = props
|
||||||
|
return (
|
||||||
|
<kbd className='flex items-center justify-center min-w-4 h-4 px-px rounded-[4px] bg-components-kbd-bg-white text-text-primary-on-surface system-kbd'>
|
||||||
|
{keyName}
|
||||||
|
</kbd>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const AdvancedActions: FC<AdvancedActionsProps> = ({
|
const AdvancedActions: FC<AdvancedActionsProps> = ({
|
||||||
isConfirmDisabled,
|
isConfirmDisabled,
|
||||||
onCancel,
|
onCancel,
|
||||||
@ -15,18 +26,31 @@ const AdvancedActions: FC<AdvancedActionsProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
useKeyPress([`${getKeyboardKeyCodeBySystem('ctrl')}.enter`], (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
onConfirm()
|
||||||
|
}, {
|
||||||
|
exactMatch: true,
|
||||||
|
useCapture: true,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex items-center gap-x-1'>
|
<div className='flex items-center gap-x-1'>
|
||||||
<Button size='small' variant='secondary' onClick={onCancel}>
|
<Button size='small' variant='secondary' onClick={onCancel}>
|
||||||
{t('common.operation.cancel')}
|
{t('common.operation.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
className='flex items-center gap-x-1'
|
||||||
disabled={isConfirmDisabled}
|
disabled={isConfirmDisabled}
|
||||||
size='small'
|
size='small'
|
||||||
variant='primary'
|
variant='primary'
|
||||||
onClick={onConfirm}
|
onClick={onConfirm}
|
||||||
>
|
>
|
||||||
{t('common.operation.confirm')}
|
<span>{t('common.operation.confirm')}</span>
|
||||||
|
<div className='flex items-center gap-x-0.5'>
|
||||||
|
<Key keyName={getKeyboardKeyNameBySystem('ctrl')} />
|
||||||
|
<Key keyName='⏎' />
|
||||||
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -20,12 +20,12 @@ export type EditData = {
|
|||||||
name: string
|
name: string
|
||||||
type: Type | ArrayType
|
type: Type | ArrayType
|
||||||
required: boolean
|
required: boolean
|
||||||
description: string
|
description?: string
|
||||||
enum?: SchemaEnumType
|
enum?: SchemaEnumType
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
description: string
|
description?: string
|
||||||
enum?: SchemaEnumType
|
enum?: SchemaEnumType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +116,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
schema.type = Type.object
|
schema.type = Type.object
|
||||||
schema.properties = {}
|
schema.properties = {}
|
||||||
schema.required = []
|
schema.required = []
|
||||||
|
schema.additionalProperties = false
|
||||||
break
|
break
|
||||||
case ArrayType.string:
|
case ArrayType.string:
|
||||||
schema.type = Type.array
|
schema.type = Type.array
|
||||||
@ -141,6 +142,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
type: Type.object,
|
type: Type.object,
|
||||||
properties: {},
|
properties: {},
|
||||||
required: [],
|
required: [],
|
||||||
|
additionalProperties: false,
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -212,8 +214,6 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
...(schema.properties || {}),
|
...(schema.properties || {}),
|
||||||
'': {
|
'': {
|
||||||
type: Type.string,
|
type: Type.string,
|
||||||
description: '',
|
|
||||||
enum: [],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
setHoveringProperty([...path, 'properties', ''].join('.'))
|
setHoveringProperty([...path, 'properties', ''].join('.'))
|
||||||
@ -223,8 +223,6 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
...(schema.items.properties || {}),
|
...(schema.items.properties || {}),
|
||||||
'': {
|
'': {
|
||||||
type: Type.string,
|
type: Type.string,
|
||||||
description: '',
|
|
||||||
enum: [],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
setHoveringProperty([...path, 'items', 'properties', ''].join('.'))
|
setHoveringProperty([...path, 'items', 'properties', ''].join('.'))
|
||||||
@ -292,6 +290,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
schema.type = Type.object
|
schema.type = Type.object
|
||||||
schema.properties = {}
|
schema.properties = {}
|
||||||
schema.required = []
|
schema.required = []
|
||||||
|
schema.additionalProperties = false
|
||||||
break
|
break
|
||||||
case ArrayType.string:
|
case ArrayType.string:
|
||||||
schema.type = Type.array
|
schema.type = Type.array
|
||||||
@ -317,6 +316,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
type: Type.object,
|
type: Type.object,
|
||||||
properties: {},
|
properties: {},
|
||||||
required: [],
|
required: [],
|
||||||
|
additionalProperties: false,
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -379,6 +379,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
schema.type = Type.object
|
schema.type = Type.object
|
||||||
schema.properties = {}
|
schema.properties = {}
|
||||||
schema.required = []
|
schema.required = []
|
||||||
|
schema.additionalProperties = false
|
||||||
break
|
break
|
||||||
case ArrayType.string:
|
case ArrayType.string:
|
||||||
schema.type = Type.array
|
schema.type = Type.array
|
||||||
@ -404,6 +405,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
|||||||
type: Type.object,
|
type: Type.object,
|
||||||
properties: {},
|
properties: {},
|
||||||
required: [],
|
required: [],
|
||||||
|
additionalProperties: false,
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -114,8 +114,8 @@ const SchemaNode: FC<SchemaNodeProps> = ({
|
|||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
required,
|
required,
|
||||||
description: schema.description || '',
|
description: schema.description,
|
||||||
enum: schema.enum || [],
|
enum: schema.enum,
|
||||||
}}
|
}}
|
||||||
path={path}
|
path={path}
|
||||||
parentPath={parentPath!}
|
parentPath={parentPath!}
|
||||||
|
@ -2,6 +2,7 @@ import { ArrayType, Type } from './types'
|
|||||||
import type { ArrayItems, Field, LLMNodeType } from './types'
|
import type { ArrayItems, Field, LLMNodeType } from './types'
|
||||||
import Ajv, { type ErrorObject } from 'ajv'
|
import Ajv, { type ErrorObject } from 'ajv'
|
||||||
import draft7MetaSchema from 'ajv/dist/refs/json-schema-draft-07.json'
|
import draft7MetaSchema from 'ajv/dist/refs/json-schema-draft-07.json'
|
||||||
|
import produce from 'immer'
|
||||||
|
|
||||||
export const checkNodeValid = (payload: LLMNodeType) => {
|
export const checkNodeValid = (payload: LLMNodeType) => {
|
||||||
return true
|
return true
|
||||||
@ -91,11 +92,13 @@ const ajv = new Ajv({
|
|||||||
ajv.addMetaSchema(draft7MetaSchema)
|
ajv.addMetaSchema(draft7MetaSchema)
|
||||||
|
|
||||||
export const validateSchemaAgainstDraft7 = (schemaToValidate: any) => {
|
export const validateSchemaAgainstDraft7 = (schemaToValidate: any) => {
|
||||||
|
const schema = produce(schemaToValidate, (draft: any) => {
|
||||||
// Make sure the schema has the $schema property for draft-07
|
// Make sure the schema has the $schema property for draft-07
|
||||||
if (!schemaToValidate.$schema)
|
if (!draft.$schema)
|
||||||
schemaToValidate.$schema = 'http://json-schema.org/draft-07/schema#'
|
draft.$schema = 'http://json-schema.org/draft-07/schema#'
|
||||||
|
})
|
||||||
|
|
||||||
const valid = ajv.validateSchema(schemaToValidate)
|
const valid = ajv.validateSchema(schema)
|
||||||
|
|
||||||
return valid ? [] : ajv.errors || []
|
return valid ? [] : ajv.errors || []
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user