feat: metadata panel
parent
b568947e00
commit
10fccd2b3f
@ -0,0 +1,26 @@
|
|||||||
|
'use client'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
label: string
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const Field: FC<Props> = ({
|
||||||
|
label,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className='flex items-start space-x-2'>
|
||||||
|
<div className='shrink-0 flex w-[128px] truncate pt-1 h-6 items-center text-text-tertiary system-xs-medium'>
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
<div className='shrink-0 w-[244px]'>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(Field)
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
'use client'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { DataType, type MetadataItemWithValue } from '../types'
|
||||||
|
import InfoGroup from './info-group'
|
||||||
|
import NoData from './no-data'
|
||||||
|
import Button from '@/app/components/base/button'
|
||||||
|
import { RiEditLine } from '@remixicon/react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
const MetadataDocument: FC = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [isEdit, setIsEdit] = useState(false)
|
||||||
|
|
||||||
|
const [list, setList] = useState<MetadataItemWithValue[]>([
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: 'Doc type',
|
||||||
|
value: 'PDF',
|
||||||
|
type: DataType.string,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: 'Title',
|
||||||
|
value: 'PDF',
|
||||||
|
type: DataType.string,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const hasData = list.length > 0
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{hasData ? (
|
||||||
|
<InfoGroup
|
||||||
|
title='Metadata'
|
||||||
|
titleTooltip='Metadata serves as a critical filter that enhances the accuracy and relevance of information retrieval. You can modify and add metadata for this document here.'
|
||||||
|
list={list}
|
||||||
|
headerRight={isEdit ? <div>Save</div> : <Button variant='ghost' onClick={() => setIsEdit(true)}>
|
||||||
|
<RiEditLine className='size-3.5 text-text-tertiary cursor-pointer' />
|
||||||
|
<div>{t('common.operation.edit')}</div>
|
||||||
|
</Button>}
|
||||||
|
isEdit={isEdit}
|
||||||
|
onChange={(item) => {
|
||||||
|
const newList = list.map(i => (i.name === item.name ? item : i))
|
||||||
|
setList(newList)
|
||||||
|
}}
|
||||||
|
onDelete={(item) => {
|
||||||
|
const newList = list.filter(i => i.name !== item.name)
|
||||||
|
setList(newList)
|
||||||
|
}}
|
||||||
|
onAdd={() => {
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
) : (
|
||||||
|
<NoData onStart={() => { }} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(MetadataDocument)
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
'use client'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
import type { MetadataItemWithValue } from '../types'
|
||||||
|
import Field from './field'
|
||||||
|
import InputCombined from '../edit-metadata-batch/input-combined'
|
||||||
|
import { RiDeleteBinLine } from '@remixicon/react'
|
||||||
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: string
|
||||||
|
titleTooltip?: string
|
||||||
|
headerRight?: React.ReactNode
|
||||||
|
list: MetadataItemWithValue[]
|
||||||
|
isEdit?: boolean
|
||||||
|
onChange?: (item: MetadataItemWithValue) => void
|
||||||
|
onDelete?: (item: MetadataItemWithValue) => void
|
||||||
|
onAdd?: (item: MetadataItemWithValue) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const InfoGroup: FC<Props> = ({
|
||||||
|
title,
|
||||||
|
titleTooltip,
|
||||||
|
headerRight,
|
||||||
|
list,
|
||||||
|
isEdit,
|
||||||
|
onChange,
|
||||||
|
onDelete,
|
||||||
|
onAdd,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='flex items-center justify-between'>
|
||||||
|
<div className='flex items-center space-x-1'>
|
||||||
|
<div className='system-xs-medium text-text-secondary'>{title}</div>
|
||||||
|
{titleTooltip && (
|
||||||
|
<Tooltip popupContent={titleTooltip} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{headerRight}
|
||||||
|
{/* <div className='flex px-1.5 rounded-md hover:bg-components-button-tertiary-bg-hover items-center h-6 space-x-1 cursor-pointer' onClick={() => setIsEdit(true)}>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
<div className='space-y-1'>
|
||||||
|
{list.map((item, i) => (
|
||||||
|
<Field key={item.id || `${i}`} label={item.name}>
|
||||||
|
{isEdit ? (
|
||||||
|
<div className='flex items-center space-x-0.5'>
|
||||||
|
<InputCombined
|
||||||
|
className='h-6'
|
||||||
|
type={item.type}
|
||||||
|
value={item.value}
|
||||||
|
onChange={value => onChange?.({ ...item, value })}
|
||||||
|
/>
|
||||||
|
<div className='shrink-0 p-1 rounded-md text-text-tertiary hover:text-text-destructive hover:bg-state-destructive-hover cursor-pointer'>
|
||||||
|
<RiDeleteBinLine className='size-4' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (<div className='system-xs-regular text-text-secondary'>{item.value}</div>)}
|
||||||
|
</Field>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default React.memo(InfoGroup)
|
||||||
Loading…
Reference in New Issue