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
52cf3c98
Commit
52cf3c98
authored
Jul 25, 2023
by
StyleZhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: segment detail style
parent
f53d3343
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
300 additions
and
169 deletions
+300
-169
edit-03.svg
...ponents/base/icons/assets/vender/line/general/edit-03.svg
+5
-0
Edit03.json
...components/base/icons/src/vender/line/general/Edit03.json
+39
-0
Edit03.tsx
.../components/base/icons/src/vender/line/general/Edit03.tsx
+14
-0
index.ts
...pp/components/base/icons/src/vender/line/general/index.ts
+1
-0
SegmentCard.tsx
...nents/datasets/documents/detail/completed/SegmentCard.tsx
+139
-111
index.tsx
.../components/datasets/documents/detail/completed/index.tsx
+55
-27
hit-detail.tsx
web/app/components/datasets/hit-testing/hit-detail.tsx
+47
-31
No files found.
web/app/components/base/icons/assets/vender/line/general/edit-03.svg
0 → 100644
View file @
52cf3c98
<svg
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<g
id=
"Icon"
>
<path
id=
"Icon_2"
d=
"M7.99998 13.3332H14M2 13.3332H3.11636C3.44248 13.3332 3.60554 13.3332 3.75899 13.2963C3.89504 13.2637 4.0251 13.2098 4.1444 13.1367C4.27895 13.0542 4.39425 12.9389 4.62486 12.7083L13 4.33316C13.5523 3.78087 13.5523 2.88544 13 2.33316C12.4477 1.78087 11.5523 1.78087 11 2.33316L2.62484 10.7083C2.39424 10.9389 2.27894 11.0542 2.19648 11.1888C2.12338 11.3081 2.0695 11.4381 2.03684 11.5742C2 11.7276 2 11.8907 2 12.2168V13.3332Z"
stroke=
"#667085"
stroke-width=
"1.5"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</g>
</svg>
web/app/components/base/icons/src/vender/line/general/Edit03.json
0 → 100644
View file @
52cf3c98
{
"icon"
:
{
"type"
:
"element"
,
"isRootNode"
:
true
,
"name"
:
"svg"
,
"attributes"
:
{
"width"
:
"16"
,
"height"
:
"16"
,
"viewBox"
:
"0 0 16 16"
,
"fill"
:
"none"
,
"xmlns"
:
"http://www.w3.org/2000/svg"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"g"
,
"attributes"
:
{
"id"
:
"Icon"
},
"children"
:
[
{
"type"
:
"element"
,
"name"
:
"path"
,
"attributes"
:
{
"id"
:
"Icon_2"
,
"d"
:
"M7.99998 13.3332H14M2 13.3332H3.11636C3.44248 13.3332 3.60554 13.3332 3.75899 13.2963C3.89504 13.2637 4.0251 13.2098 4.1444 13.1367C4.27895 13.0542 4.39425 12.9389 4.62486 12.7083L13 4.33316C13.5523 3.78087 13.5523 2.88544 13 2.33316C12.4477 1.78087 11.5523 1.78087 11 2.33316L2.62484 10.7083C2.39424 10.9389 2.27894 11.0542 2.19648 11.1888C2.12338 11.3081 2.0695 11.4381 2.03684 11.5742C2 11.7276 2 11.8907 2 12.2168V13.3332Z"
,
"stroke"
:
"currentColor"
,
"stroke-width"
:
"1.5"
,
"stroke-linecap"
:
"round"
,
"stroke-linejoin"
:
"round"
},
"children"
:
[]
}
]
}
]
},
"name"
:
"Edit03"
}
\ No newline at end of file
web/app/components/base/icons/src/vender/line/general/Edit03.tsx
0 → 100644
View file @
52cf3c98
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import
*
as
React
from
'react'
import
data
from
'./Edit03.json'
import
IconBase
from
'@/app/components/base/icons/IconBase'
import
type
{
IconBaseProps
,
IconData
}
from
'@/app/components/base/icons/IconBase'
const
Icon
=
React
.
forwardRef
<
React
.
MutableRefObject
<
SVGElement
>
,
Omit
<
IconBaseProps
,
'data'
>>
((
props
,
ref
,
)
=>
<
IconBase
{
...
props
}
ref=
{
ref
}
data=
{
data
as
IconData
}
/>)
export
default
Icon
web/app/components/base/icons/src/vender/line/general/index.ts
View file @
52cf3c98
export
{
default
as
Edit03
}
from
'./Edit03'
export
{
default
as
Loading02
}
from
'./Loading02'
export
{
default
as
Trash03
}
from
'./Trash03'
export
{
default
as
XClose
}
from
'./XClose'
...
...
web/app/components/datasets/documents/detail/completed/SegmentCard.tsx
View file @
52cf3c98
This diff is collapsed.
Click to expand it.
web/app/components/datasets/documents/detail/completed/index.tsx
View file @
52cf3c98
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
memo
,
use
State
,
useEffect
,
useMemo
}
from
'react'
import
React
,
{
memo
,
use
Effect
,
useMemo
,
useState
}
from
'react'
import
{
HashtagIcon
}
from
'@heroicons/react/24/solid'
import
{
useTranslation
}
from
'react-i18next'
import
{
useContext
}
from
'use-context-selector'
import
{
omitBy
,
isNil
,
debounce
}
from
'lodash-es'
import
{
formatNumber
}
from
'@/utils/format
'
import
{
debounce
,
isNil
,
omitBy
}
from
'lodash-es'
import
cn
from
'classnames
'
import
{
StatusItem
}
from
'../../list'
import
{
DocumentContext
}
from
'../index'
import
s
from
'./style.module.css'
import
InfiniteVirtualList
from
'./InfiniteVirtualList'
import
{
formatNumber
}
from
'@/utils/format'
import
Modal
from
'@/app/components/base/modal'
import
Switch
from
'@/app/components/base/switch'
import
Divider
from
'@/app/components/base/divider'
import
Input
from
'@/app/components/base/input'
import
Loading
from
'@/app/components/base/loading'
import
{
ToastContext
}
from
'@/app/components/base/toast'
import
{
SimpleSelect
,
Item
}
from
'@/app/components/base/select'
import
type
{
Item
}
from
'@/app/components/base/select'
import
{
SimpleSelect
}
from
'@/app/components/base/select'
import
{
disableSegment
,
enableSegment
,
fetchSegments
}
from
'@/service/datasets'
import
type
{
SegmentDetailModel
,
Segments
Response
,
SegmentsQuery
}
from
'@/models/datasets'
import
type
{
SegmentDetailModel
,
Segments
Query
,
SegmentsResponse
}
from
'@/models/datasets'
import
{
asyncRunSafe
}
from
'@/utils'
import
type
{
CommonResponse
}
from
'@/models/common'
import
InfiniteVirtualList
from
"./InfiniteVirtualList"
;
import
cn
from
'classnames'
import
{
Edit03
,
XClose
}
from
'@/app/components/base/icons/src/vender/line/general'
export
const
SegmentIndexTag
:
FC
<
{
positionId
:
string
|
number
;
className
?:
string
}
>
=
({
positionId
,
className
})
=>
{
const
localPositionId
=
useMemo
(()
=>
{
...
...
@@ -41,19 +42,46 @@ export const SegmentIndexTag: FC<{ positionId: string | number; className?: stri
type
ISegmentDetailProps
=
{
segInfo
?:
Partial
<
SegmentDetailModel
>
&
{
id
:
string
}
onChangeSwitch
?:
(
segId
:
string
,
enabled
:
boolean
)
=>
Promise
<
void
>
onCancel
:
()
=>
void
}
/**
* Show all the contents of the segment
*/
export
const
SegmentDetail
:
FC
<
ISegmentDetailProps
>
=
memo
(({
segInfo
,
onChangeSwitch
})
=>
{
onChangeSwitch
,
onCancel
,
})
=>
{
const
{
t
}
=
useTranslation
()
const
renderContent
=
()
=>
{
if
(
segInfo
?.
answer
)
{
return
(
<>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
QUESTION
</
div
>
<
div
className=
'mb-4 text-md text-gray-800'
>
{
segInfo
.
answer
}
</
div
>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
ANSWER
</
div
>
<
div
className=
'text-md text-gray-800'
>
{
segInfo
.
content
}
</
div
>
</>
)
}
return
segInfo
?.
content
}
return
(
<
div
className=
{
'flex flex-col'
}
>
<
SegmentIndexTag
positionId=
{
segInfo
?.
position
||
''
}
className=
'w-fit mb-6'
/>
<
div
className=
{
s
.
segModalContent
}
>
{
segInfo
?.
content
}
</
div
>
<
div
className=
{
'flex flex-col relative'
}
>
<
div
className=
'absolute right-0 top-0 flex items-center'
>
<
div
className=
'flex justify-center items-center w-6 h-6 hover:bg-gray-100 rounded-md cursor-pointer'
>
<
Edit03
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
<
div
className=
'mx-3 w-[1px] h-3 bg-gray-200'
/>
<
div
className=
'flex justify-center items-center w-6 h-6 cursor-pointer'
onClick=
{
onCancel
}
>
<
XClose
className=
'w-4 h-4 text-gray-500'
/>
</
div
>
</
div
>
<
SegmentIndexTag
positionId=
{
segInfo
?.
position
||
''
}
className=
'w-fit mt-[2px] mb-6'
/>
<
div
className=
{
s
.
segModalContent
}
>
{
renderContent
()
}
</
div
>
<
div
className=
{
s
.
keywordTitle
}
>
{
t
(
'datasetDocuments.segment.keywords'
)
}
</
div
>
<
div
className=
{
s
.
keywordWrapper
}
>
{
!
segInfo
?.
keywords
?.
length
...
...
@@ -74,7 +102,7 @@ export const SegmentDetail: FC<ISegmentDetailProps> = memo(({
<
Switch
size=
'md'
defaultValue=
{
segInfo
?.
enabled
}
onChange=
{
async
val
=>
{
onChange=
{
async
(
val
)
=>
{
await
onChangeSwitch
?.(
segInfo
?.
id
||
''
,
val
)
}
}
/>
...
...
@@ -115,18 +143,12 @@ const Completed: FC<ICompletedProps> = () => {
const
[
loading
,
setLoading
]
=
useState
(
false
)
const
[
total
,
setTotal
]
=
useState
<
number
|
undefined
>
()
useEffect
(()
=>
{
if
(
lastSegmentsRes
!==
undefined
)
{
getSegments
(
false
)
}
},
[
selectedStatus
,
searchValue
])
const
onChangeStatus
=
({
value
}:
Item
)
=>
{
setSelectedStatus
(
value
===
'all'
?
'all'
:
!!
value
)
}
const
getSegments
=
async
(
needLastId
?:
boolean
)
=>
{
const
finalLastId
=
lastSegmentsRes
?.
data
?.[
lastSegmentsRes
.
data
.
length
-
1
]?.
id
||
''
;
const
finalLastId
=
lastSegmentsRes
?.
data
?.[
lastSegmentsRes
.
data
.
length
-
1
]?.
id
||
''
setLoading
(
true
)
const
[
e
,
res
]
=
await
asyncRunSafe
<
SegmentsResponse
>
(
fetchSegments
({
datasetId
,
...
...
@@ -136,16 +158,22 @@ const Completed: FC<ICompletedProps> = () => {
limit
:
9
,
keyword
:
searchValue
,
enabled
:
selectedStatus
===
'all'
?
'all'
:
!!
selectedStatus
,
},
isNil
)
as
SegmentsQuery
},
isNil
)
as
SegmentsQuery
,
})
as
Promise
<
SegmentsResponse
>
)
if
(
!
e
)
{
setAllSegments
([...(
!
needLastId
?
[]
:
allSegments
),
...
splitArray
(
res
.
data
||
[])])
setLastSegmentsRes
(
res
)
if
(
!
lastSegmentsRes
)
{
setTotal
(
res
?.
total
||
0
)
}
if
(
!
lastSegmentsRes
)
setTotal
(
res
?.
total
||
0
)
}
setLoading
(
false
)
}
useEffect
(()
=>
{
if
(
lastSegmentsRes
!==
undefined
)
getSegments
(
false
)
},
[
selectedStatus
,
searchValue
])
const
onClickCard
=
(
detail
:
SegmentDetailModel
)
=>
{
setCurrSegment
({
segInfo
:
detail
,
showModal
:
true
})
}
...
...
@@ -161,13 +189,13 @@ const Completed: FC<ICompletedProps> = () => {
notify
({
type
:
'success'
,
message
:
t
(
'common.actionMsg.modifiedSuccessfully'
)
})
for
(
const
item
of
allSegments
)
{
for
(
const
seg
of
item
)
{
if
(
seg
.
id
===
segId
)
{
if
(
seg
.
id
===
segId
)
seg
.
enabled
=
enabled
}
}
}
setAllSegments
([...
allSegments
])
}
else
{
}
else
{
notify
({
type
:
'error'
,
message
:
t
(
'common.actionMsg.modificationFailed'
)
})
}
}
...
...
@@ -196,8 +224,8 @@ const Completed: FC<ICompletedProps> = () => {
onChangeSwitch=
{
onChangeSwitch
}
onClick=
{
onClickCard
}
/>
<
Modal
isShow=
{
currSegment
.
showModal
}
onClose=
{
onCloseModal
}
className=
'!max-w-[640px]'
closable
>
<
SegmentDetail
segInfo=
{
currSegment
.
segInfo
??
{
id
:
''
}
}
onChangeSwitch=
{
onChangeSwitch
}
/>
<
Modal
isShow=
{
currSegment
.
showModal
}
onClose=
{
()
=>
{}
}
className=
'!max-w-[640px]'
>
<
SegmentDetail
segInfo=
{
currSegment
.
segInfo
??
{
id
:
''
}
}
onChangeSwitch=
{
onChangeSwitch
}
onCancel=
{
onCloseModal
}
/>
</
Modal
>
</>
)
...
...
web/app/components/datasets/hit-testing/hit-detail.tsx
View file @
52cf3c98
import
React
,
{
FC
}
from
"react"
;
import
cn
from
"classnames"
;
import
{
SegmentDetailModel
}
from
"@/models/datasets"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
Divider
from
"@/app/components/base/divider"
;
import
{
SegmentIndexTag
}
from
"../documents/detail/completed"
;
import
s
from
"../documents/detail/completed/style.module.css"
;
import
ReactECharts
from
"echarts-for-react"
;
import
type
{
FC
}
from
'react'
import
React
from
'react'
import
cn
from
'classnames'
import
{
useTranslation
}
from
'react-i18next'
import
ReactECharts
from
'echarts-for-react'
import
{
SegmentIndexTag
}
from
'../documents/detail/completed'
import
s
from
'../documents/detail/completed/style.module.css'
import
type
{
SegmentDetailModel
}
from
'@/models/datasets'
import
Divider
from
'@/app/components/base/divider'
type
IScatterChartProps
=
{
data
:
Array
<
number
[]
>
...
...
@@ -19,8 +20,8 @@ const ScatterChart: FC<IScatterChartProps> = ({ data, curr }) => {
tooltip
:
{
trigger
:
'item'
,
axisPointer
:
{
type
:
'cross'
}
type
:
'cross'
,
}
,
},
series
:
[
{
...
...
@@ -32,49 +33,64 @@ const ScatterChart: FC<IScatterChartProps> = ({ data, curr }) => {
type
:
'scatter'
,
symbolSize
:
5
,
data
,
}
]
}
;
}
,
]
,
}
return
(
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
380
,
width
:
430
}
}
/>
)
}
type
IHitDetailProps
=
{
segInfo
?:
Partial
<
SegmentDetailModel
>
&
{
id
:
string
}
;
vectorInfo
?:
{
curr
:
Array
<
number
[]
>
;
points
:
Array
<
number
[]
>
}
;
}
;
segInfo
?:
Partial
<
SegmentDetailModel
>
&
{
id
:
string
}
vectorInfo
?:
{
curr
:
Array
<
number
[]
>
;
points
:
Array
<
number
[]
>
}
}
const
HitDetail
:
FC
<
IHitDetailProps
>
=
({
segInfo
,
vectorInfo
})
=>
{
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
()
const
renderContent
=
()
=>
{
if
(
segInfo
?.
answer
)
{
return
(
<>
<
div
className=
'mt-2 mb-1 text-xs font-medium text-gray-500'
>
QUESTION
</
div
>
<
div
className=
'mb-4 text-md text-gray-800'
>
{
segInfo
.
answer
}
</
div
>
<
div
className=
'mb-1 text-xs font-medium text-gray-500'
>
ANSWER
</
div
>
<
div
className=
'text-md text-gray-800'
>
{
segInfo
.
content
}
</
div
>
</>
)
}
return
segInfo
?.
content
}
return
(
<
div
className=
{
"flex flex-row"
}
>
<
div
className=
{
'flex flex-row'
}
>
<
div
className=
"flex-1 bg-gray-25 p-6"
>
<
div
className=
"flex items-center"
>
<
SegmentIndexTag
positionId=
{
segInfo
?.
position
||
""
}
positionId=
{
segInfo
?.
position
||
''
}
className=
"w-fit mr-6"
/>
<
div
className=
{
cn
(
s
.
commonIcon
,
s
.
typeSquareIcon
)
}
/>
<
span
className=
{
cn
(
"mr-6"
,
s
.
numberInfo
)
}
>
{
segInfo
?.
word_count
}
{
t
(
"datasetDocuments.segment.characters"
)
}
<
span
className=
{
cn
(
'mr-6'
,
s
.
numberInfo
)
}
>
{
segInfo
?.
word_count
}
{
t
(
'datasetDocuments.segment.characters'
)
}
</
span
>
<
div
className=
{
cn
(
s
.
commonIcon
,
s
.
targetIcon
)
}
/>
<
span
className=
{
s
.
numberInfo
}
>
{
segInfo
?.
hit_count
}
{
t
(
"datasetDocuments.segment.hitCount"
)
}
{
segInfo
?.
hit_count
}
{
t
(
'datasetDocuments.segment.hitCount'
)
}
</
span
>
</
div
>
<
Divider
/>
<
div
className=
{
s
.
segModalContent
}
>
{
segInfo
?.
content
}
</
div
>
<
div
className=
{
s
.
segModalContent
}
>
{
renderContent
()
}
</
div
>
<
div
className=
{
s
.
keywordTitle
}
>
{
t
(
"datasetDocuments.segment.keywords"
)
}
{
t
(
'datasetDocuments.segment.keywords'
)
}
</
div
>
<
div
className=
{
s
.
keywordWrapper
}
>
{
!
segInfo
?.
keywords
?.
length
?
"-"
?
'-'
:
segInfo
?.
keywords
?.
map
((
word
:
any
)
=>
{
return
<
div
className=
{
s
.
keyword
}
>
{
word
}
</
div
>
;
return
<
div
className=
{
s
.
keyword
}
>
{
word
}
</
div
>
})
}
</
div
>
</
div
>
...
...
@@ -82,18 +98,18 @@ const HitDetail: FC<IHitDetailProps> = ({ segInfo, vectorInfo }) => {
<
div
className=
"flex items-center"
>
<
div
className=
{
cn
(
s
.
commonIcon
,
s
.
bezierCurveIcon
)
}
/>
<
span
className=
{
s
.
numberInfo
}
>
{
t
(
"datasetDocuments.segment.vectorHash"
)
}
{
t
(
'datasetDocuments.segment.vectorHash'
)
}
</
span
>
</
div
>
<
div
className=
{
cn
(
s
.
numberInfo
,
"w-[400px] truncate text-gray-700 mt-1"
)
}
className=
{
cn
(
s
.
numberInfo
,
'w-[400px] truncate text-gray-700 mt-1'
)
}
>
{
segInfo
?.
index_node_hash
}
</
div
>
<
ScatterChart
data=
{
vectorInfo
?.
points
||
[]
}
curr=
{
vectorInfo
?.
curr
||
[]
}
/>
</
div
>
</
div
>
)
;
}
;
)
}
export
default
HitDetail
;
export
default
HitDetail
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