Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
7fa25934
Commit
7fa25934
authored
Feb 28, 2024
by
Joel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: key value input
parent
649c3d07
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
229 additions
and
65 deletions
+229
-65
remove-button.tsx
...ponents/workflow/nodes/_base/components/remove-button.tsx
+25
-0
key-value-item.tsx
...ponents/workflow/nodes/http/components/key-value-item.tsx
+0
-61
input-item.tsx
...s/workflow/nodes/http/components/key-value/input-item.tsx
+64
-0
item.tsx
...ponents/workflow/nodes/http/components/key-value/item.tsx
+63
-0
list.tsx
...ponents/workflow/nodes/http/components/key-value/list.tsx
+61
-0
mock.ts
web/app/components/workflow/nodes/http/mock.ts
+5
-3
panel.tsx
web/app/components/workflow/nodes/http/panel.tsx
+11
-1
No files found.
web/app/components/workflow/nodes/_base/components/remove-button.tsx
0 → 100644
View file @
7fa25934
'use client'
import
type
{
FC
}
from
'react'
import
React
from
'react'
import
cn
from
'classnames'
import
{
Trash03
}
from
'@/app/components/base/icons/src/vender/line/general'
type
Props
=
{
className
?:
string
onClick
:
(
e
:
React
.
MouseEvent
)
=>
void
}
const
Remove
:
FC
<
Props
>
=
({
className
,
onClick
,
})
=>
{
return
(
<
div
className=
{
cn
(
className
,
'p-1 cursor-pointer rounded-md hover:bg-black/5 text-gray-500 hover:text-gray-800'
)
}
onClick=
{
onClick
}
>
<
Trash03
className=
'w-4 h-4'
/>
</
div
>
)
}
export
default
React
.
memo
(
Remove
)
web/app/components/workflow/nodes/http/components/key-value-item.tsx
deleted
100644 → 0
View file @
649c3d07
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useCallback
}
from
'react'
import
{
useBoolean
}
from
'ahooks'
import
type
{
KeyValue
}
from
'../types'
import
{
Trash03
}
from
'@/app/components/base/icons/src/vender/line/general'
type
Props
=
{
payload
:
KeyValue
onChange
:
(
newPayload
:
KeyValue
)
=>
void
onRemove
:
()
=>
void
isLastItem
:
boolean
onAdd
:
()
=>
void
}
const
KeyValueItem
:
FC
<
Props
>
=
({
payload
,
onChange
,
onRemove
,
isLastItem
,
onAdd
,
})
=>
{
const
[
isKeyEditing
,
{
setTrue
:
setIsKeyEditing
,
setFalse
:
setIsKeyEditingFalse
,
}]
=
useBoolean
(
false
)
const
handleKeyChange
=
useCallback
((
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
onChange
({
key
:
e
.
target
.
value
,
value
:
payload
.
value
,
})
},
[])
return
(
<
div
>
<
div
>
{
isKeyEditing
?
(
<
input
type=
'text'
value=
{
payload
.
key
}
onChange=
{
handleKeyChange
}
onBlur=
{
setIsKeyEditingFalse
}
/>
)
:
<
div
onClick=
{
setIsKeyEditing
}
>
{
payload
.
key
}
</
div
>
}
</
div
>
<
div
>
{
payload
.
value
}
<
div
className=
'p-1 cursor-pointer rounded-md hover:bg-black/5'
onClick=
{
onRemove
}
>
<
Trash03
className=
'w-4 h-4'
/>
</
div
>
</
div
>
</
div
>
)
}
export
default
React
.
memo
(
KeyValueItem
)
web/app/components/workflow/nodes/http/components/key-value/input-item.tsx
0 → 100644
View file @
7fa25934
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useCallback
}
from
'react'
import
{
useBoolean
}
from
'ahooks'
import
cn
from
'classnames'
import
RemoveButton
from
'@/app/components/workflow/nodes/_base/components/remove-button'
type
Props
=
{
className
?:
string
value
:
string
onChange
:
(
newValue
:
string
)
=>
void
hasRemove
:
boolean
onRemove
?:
()
=>
void
}
const
InputItem
:
FC
<
Props
>
=
({
className
,
value
,
onChange
,
hasRemove
,
onRemove
,
})
=>
{
const
[
isEdit
,
{
setTrue
:
setIsEditTrue
,
setFalse
:
setIsEditFalse
,
}]
=
useBoolean
(
false
)
const
handleChange
=
useCallback
((
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
onChange
(
e
.
target
.
value
)
},
[
onChange
])
const
handleRemove
=
useCallback
((
e
:
React
.
MouseEvent
)
=>
{
e
.
stopPropagation
()
onRemove
?.()
},
[
onRemove
])
return
(
<
div
className=
{
cn
(
className
,
!
isEdit
&&
'hover:bg-gray-50 hover:cursor-text'
,
'relative flex h-full items-center pl-2'
)
}
>
{
isEdit
?
(
<
input
type=
'text'
className=
'w-full h-[18px] leading-[18px] pl-0.5 text-gray-900 text-xs font-normal placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200'
value=
{
value
}
onChange=
{
handleChange
}
onBlur=
{
setIsEditFalse
}
autoFocus
/>
)
:
<
div
className=
"pl-0.5 w-full h-[18px] leading-[18px]"
onClick=
{
setIsEditTrue
}
>
<
div
className=
'text-gray-900 text-xs font-normal'
>
{
value
}
</
div
>
{
hasRemove
&&
!
isEdit
&&
(
<
RemoveButton
className=
'group-hover:block hidden absolute right-1 top-0.5'
onClick=
{
handleRemove
}
/>
)
}
</
div
>
}
</
div
>
)
}
export
default
React
.
memo
(
InputItem
)
web/app/components/workflow/nodes/http/components/key-value/item.tsx
0 → 100644
View file @
7fa25934
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useCallback
}
from
'react'
import
cn
from
'classnames'
import
produce
from
'immer'
import
type
{
KeyValue
}
from
'../../types'
import
InputItem
from
'./input-item'
type
Props
=
{
className
?:
string
readonly
:
boolean
canRemove
:
boolean
payload
:
KeyValue
onChange
:
(
newPayload
:
KeyValue
)
=>
void
onRemove
:
()
=>
void
isLastItem
:
boolean
onAdd
:
()
=>
void
}
const
KeyValueItem
:
FC
<
Props
>
=
({
className
,
readonly
,
canRemove
,
payload
,
onChange
,
onRemove
,
isLastItem
,
onAdd
,
})
=>
{
const
handleChange
=
useCallback
((
key
:
string
)
=>
{
return
(
value
:
string
)
=>
{
const
newPayload
=
produce
(
payload
,
(
draft
:
any
)
=>
{
draft
[
key
]
=
value
})
onChange
(
newPayload
)
if
(
key
===
'value'
&&
isLastItem
)
onAdd
()
}
},
[
onChange
,
onAdd
,
isLastItem
,
payload
])
return
(
// group class name is for hover row show remove button
<
div
className=
{
cn
(
className
,
'group flex items-center h-7 border-t border-gray-200'
)
}
>
<
div
className=
'w-1/2 h-full border-r border-gray-200'
>
<
InputItem
className=
'pr-2.5'
value=
{
payload
.
key
}
onChange=
{
handleChange
(
'key'
)
}
hasRemove=
{
false
}
/>
</
div
>
<
div
className=
'w-1/2 h-full'
>
<
InputItem
className=
'pr-1'
value=
{
payload
.
value
}
onChange=
{
handleChange
(
'value'
)
}
hasRemove=
{
!
readonly
&&
canRemove
}
onRemove=
{
onRemove
}
/>
</
div
>
</
div
>
)
}
export
default
React
.
memo
(
KeyValueItem
)
web/app/components/workflow/nodes/http/components/key-value
-
list.tsx
→
web/app/components/workflow/nodes/http/components/key-value
/
list.tsx
View file @
7fa25934
'use client'
import
type
{
FC
}
from
'react'
import
React
from
'react'
import
type
{
KeyValue
}
from
'../types
'
import
KeyValueItem
from
'./key-value-item
'
import
React
,
{
useCallback
}
from
'react'
import
produce
from
'immer
'
import
type
{
KeyValue
}
from
'../../types
'
import
KeyValueItem
from
'./item'
type
Props
=
{
readonly
:
boolean
list
:
KeyValue
[]
onChange
:
(
newList
:
KeyValue
[])
=>
void
onAdd
:
()
=>
void
}
const
KeyValueList
:
FC
<
Props
>
=
({
readonly
,
list
,
onChange
,
onAdd
,
})
=>
{
const
handleChange
=
useCallback
((
index
:
number
)
=>
{
return
(
newItem
:
KeyValue
)
=>
{
const
newList
=
produce
(
list
,
(
draft
:
any
)
=>
{
draft
[
index
]
=
newItem
})
onChange
(
newList
)
}
},
[
list
,
onChange
])
const
handleRemove
=
useCallback
((
index
:
number
)
=>
{
return
()
=>
{
const
newList
=
produce
(
list
,
(
draft
:
any
)
=>
{
draft
.
splice
(
index
,
1
)
})
onChange
(
newList
)
}
},
[
list
,
onChange
])
return
(
<
div
>
<
div
>
<
div
>
key
</
div
>
<
div
>
value
</
div
>
<
div
className=
'border border-gray-200 rounded-lg overflow-hidden'
>
<
div
className=
'flex items-center h-7 leading-7 text-xs font-medium text-gray-500 uppercase'
>
<
div
className=
'w-1/2 h-full pl-3 border-r border-gray-200'
>
key
</
div
>
<
div
className=
'w-1/2 h-full pl-3'
>
value
</
div
>
</
div
>
{
list
.
map
((
item
,
index
)
=>
(
<
KeyValueItem
key=
{
index
}
payload=
{
item
}
onChange=
{
(
newItem
)
=>
{
const
newList
=
[...
list
]
newList
[
index
]
=
newItem
onChange
(
newList
)
}
}
onRemove=
{
()
=>
{
const
newList
=
[...
list
]
newList
.
splice
(
index
,
1
)
onChange
(
newList
)
}
}
onChange=
{
handleChange
(
index
)
}
onRemove=
{
handleRemove
(
index
)
}
isLastItem=
{
index
===
list
.
length
-
1
}
onAdd=
{
onAdd
}
readonly=
{
readonly
}
canRemove=
{
list
.
length
>
1
}
/>
))
}
...
...
web/app/components/workflow/nodes/http/mock.ts
View file @
7fa25934
import
{
BlockEnum
}
from
'../../types'
import
{
MethodEnum
}
from
'./types'
import
type
{
HttpNodeType
}
from
'./types'
export
const
mockData
:
HttpNodeType
=
{
title
:
'Test'
,
desc
:
'Test'
,
type
:
'Test'
,
type
:
BlockEnum
.
HttpRequest
,
variables
:
[
{
variable
:
'name'
,
...
...
@@ -14,9 +16,9 @@ export const mockData: HttpNodeType = {
value_selector
:
[
'bbb'
,
'b'
,
'c'
],
},
],
method
:
'get'
,
method
:
MethodEnum
.
get
,
url
:
'https://api.dify.com/xx'
,
headers
:
''
,
headers
:
'
Content-Type: application/json
\
nAccept: */*
'
,
params
:
''
,
body
:
{
type
:
'json'
,
...
...
web/app/components/workflow/nodes/http/panel.tsx
View file @
7fa25934
...
...
@@ -3,11 +3,13 @@ import { useTranslation } from 'react-i18next'
import
useConfig
from
'./use-config'
import
{
mockData
}
from
'./mock'
import
ApiInput
from
'./components/api-input'
import
KeyValueList
from
'./components/key-value/list'
import
VarList
from
'@/app/components/workflow/nodes/_base/components/variable/var-list'
import
Field
from
'@/app/components/workflow/nodes/_base/components/field'
import
AddButton
from
'@/app/components/base/button/add-button'
import
Split
from
'@/app/components/workflow/nodes/_base/components/split'
import
OutputVars
,
{
VarItem
}
from
'@/app/components/workflow/nodes/_base/components/output-vars'
const
i18nPrefix
=
'workflow.nodes.http'
const
Panel
:
FC
=
()
=>
{
...
...
@@ -20,6 +22,9 @@ const Panel: FC = () => {
handleAddVariable
,
handleMethodChange
,
handleUrlChange
,
headers
,
setHeaders
,
addHeader
,
}
=
useConfig
(
mockData
)
return
(
...
...
@@ -51,7 +56,12 @@ const Panel: FC = () => {
<
Field
title=
{
t
(
`${i18nPrefix}.headers`
)
}
>
headers
<
KeyValueList
list=
{
headers
}
onChange=
{
setHeaders
}
onAdd=
{
addHeader
}
readonly=
{
readOnly
}
/>
</
Field
>
<
Field
title=
{
t
(
`${i18nPrefix}.params`
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment