This commit is contained in:
zxhlyh 2025-03-06 16:47:26 +08:00
commit 30f0b66f01
29 changed files with 193 additions and 54 deletions

View File

@ -522,6 +522,7 @@ class WorkflowBasedAppRunner(AppRunner):
status=event.status, status=event.status,
data=event.data, data=event.data,
metadata=event.metadata, metadata=event.metadata,
node_id=event.node_id,
) )
) )
elif isinstance(event, ParallelBranchRunStartedEvent): elif isinstance(event, ParallelBranchRunStartedEvent):

View File

@ -427,6 +427,7 @@ class QueueAgentLogEvent(AppQueueEvent):
status: str status: str
data: Mapping[str, Any] data: Mapping[str, Any]
metadata: Optional[Mapping[str, Any]] = None metadata: Optional[Mapping[str, Any]] = None
node_id: str
class QueueNodeRetryEvent(QueueNodeStartedEvent): class QueueNodeRetryEvent(QueueNodeStartedEvent):

View File

@ -817,6 +817,7 @@ class AgentLogStreamResponse(StreamResponse):
status: str status: str
data: Mapping[str, Any] data: Mapping[str, Any]
metadata: Optional[Mapping[str, Any]] = None metadata: Optional[Mapping[str, Any]] = None
node_id: str
event: StreamEvent = StreamEvent.AGENT_LOG event: StreamEvent = StreamEvent.AGENT_LOG
data: Data data: Data

View File

@ -959,5 +959,6 @@ class WorkflowCycleManage:
status=event.status, status=event.status,
data=event.data, data=event.data,
metadata=event.metadata, metadata=event.metadata,
node_id=event.node_id,
), ),
) )

View File

@ -268,6 +268,7 @@ class AgentLogEvent(BaseAgentEvent):
status: str = Field(..., description="status") status: str = Field(..., description="status")
data: Mapping[str, Any] = Field(..., description="data") data: Mapping[str, Any] = Field(..., description="data")
metadata: Optional[Mapping[str, Any]] = Field(default=None, description="metadata") metadata: Optional[Mapping[str, Any]] = Field(default=None, description="metadata")
node_id: str = Field(..., description="agent node id")
InNodeEvent = BaseNodeEvent | BaseParallelBranchEvent | BaseIterationEvent | BaseAgentEvent | BaseLoopEvent InNodeEvent = BaseNodeEvent | BaseParallelBranchEvent | BaseIterationEvent | BaseAgentEvent | BaseLoopEvent

View File

@ -18,6 +18,7 @@ from core.workflow.entities.node_entities import AgentNodeStrategyInit, NodeRunM
from core.workflow.entities.variable_pool import VariablePool, VariableValue from core.workflow.entities.variable_pool import VariablePool, VariableValue
from core.workflow.graph_engine.condition_handlers.condition_manager import ConditionManager from core.workflow.graph_engine.condition_handlers.condition_manager import ConditionManager
from core.workflow.graph_engine.entities.event import ( from core.workflow.graph_engine.entities.event import (
BaseAgentEvent,
BaseIterationEvent, BaseIterationEvent,
BaseLoopEvent, BaseLoopEvent,
GraphEngineEvent, GraphEngineEvent,
@ -502,7 +503,7 @@ class GraphEngine:
break break
yield event yield event
if event.parallel_id == parallel_id: if not isinstance(event, BaseAgentEvent) and event.parallel_id == parallel_id:
if isinstance(event, ParallelBranchRunSucceededEvent): if isinstance(event, ParallelBranchRunSucceededEvent):
succeeded_count += 1 succeeded_count += 1
if succeeded_count == len(futures): if succeeded_count == len(futures):

View File

@ -338,6 +338,7 @@ class ToolNode(BaseNode[ToolNodeData]):
data=message.message.data, data=message.message.data,
label=message.message.label, label=message.message.label,
metadata=message.message.metadata, metadata=message.message.metadata,
node_id=self.node_id,
) )
# check if the agent log is already in the list # check if the agent log is already in the list

View File

@ -153,7 +153,8 @@ services:
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
volumes: volumes:
- ./volumes/plugin_daemon:/app/storage - ./volumes/plugin_daemon:/app/storage
depends_on:
- db
# ssrf_proxy server # ssrf_proxy server
# for more information, please refer to # for more information, please refer to

View File

@ -568,7 +568,8 @@ services:
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
volumes: volumes:
- ./volumes/plugin_daemon:/app/storage - ./volumes/plugin_daemon:/app/storage
depends_on:
- db
# ssrf_proxy server # ssrf_proxy server
# for more information, please refer to # for more information, please refer to

View File

@ -1543,6 +1543,59 @@ import { Row, Col, Properties, Property, Heading, SubProperty, PropertyInstructi
<hr className='ml-0 mr-0' /> <hr className='ml-0 mr-0' />
<Heading
url='/datasets/{dataset_id}/metadata'
method='POST'
title='Create a Knowledge metadata'
name='#create_metadata'
/>
<Row>
<Col>
### POST
<Properties>
<Property name='dataset_id' type='string' key='dataset_id'>
Knowledge ID
</Property>
</Properties>
### Request Body
<Properties>
<Property name='segment' type='object' key='segment'>
- <code>type</code> (string) metadata type, required
- <code>name</code> (string) metadata name, required
</Property>
</Properties>
</Col>
<Col sticky>
<CodeGroup
title="Request"
tag="POST"
label="/datasets/{dataset_id}/metadata"
targetCode={`curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json'\\\n--data-raw '{\"segment\": {\"content\": \"1\",\"answer\": \"1\", \"keywords\": [\"a\"], \"enabled\": false}}'`}
>
```bash {{ title: 'cURL' }}
curl --location --request POST '${props.apiBaseUrl}/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}' \
--header 'Content-Type: application/json' \
--data-raw '{
"segment": {
"content": "1",
"answer": "1",
}
}'
```
</CodeGroup>
<CodeGroup title="Response">
```json {{ title: 'Response' }}
{
"doc_form": "text_model"
}
```
</CodeGroup>
</Col>
</Row>
<hr className='ml-0 mr-0' />
<Row> <Row>
<Col> <Col>
### Error message ### Error message

View File

@ -1,7 +1,7 @@
import React, { type FC } from 'react' import React, { type FC } from 'react'
import type { CalendarItemProps } from '../types' import type { CalendarItemProps } from '../types'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import dayjs from 'dayjs' import dayjs from '../utils/dayjs'
const Item: FC<CalendarItemProps> = ({ const Item: FC<CalendarItemProps> = ({
day, day,

View File

@ -22,18 +22,18 @@ const Header: FC<DatePickerHeaderProps> = ({
<RiArrowDownSLine className='w-4 h-4 text-text-tertiary' /> <RiArrowDownSLine className='w-4 h-4 text-text-tertiary' />
</button> </button>
</div> </div>
<button
onClick={onClickNextMonth}
className='p-1.5 hover:bg-state-base-hover rounded-lg'
>
<RiArrowDownSLine className='w-[18px] h-[18px] text-text-secondary' />
</button>
<button <button
onClick={onClickPrevMonth} onClick={onClickPrevMonth}
className='p-1.5 hover:bg-state-base-hover rounded-lg' className='p-1.5 hover:bg-state-base-hover rounded-lg'
> >
<RiArrowUpSLine className='w-[18px] h-[18px] text-text-secondary' /> <RiArrowUpSLine className='w-[18px] h-[18px] text-text-secondary' />
</button> </button>
<button
onClick={onClickNextMonth}
className='p-1.5 hover:bg-state-base-hover rounded-lg'
>
<RiArrowDownSLine className='w-[18px] h-[18px] text-text-secondary' />
</button>
</div> </div>
) )
} }

View File

@ -1,10 +1,16 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import dayjs, { type Dayjs } from 'dayjs'
import { RiCalendarLine, RiCloseCircleFill } from '@remixicon/react' import { RiCalendarLine, RiCloseCircleFill } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { DatePickerProps, Period } from '../types' import type { DatePickerProps, Period } from '../types'
import { ViewType } from '../types' import { ViewType } from '../types'
import { cloneTime, getDaysInMonth, getHourIn12Hour } from '../utils' import type { Dayjs } from 'dayjs'
import dayjs, {
clearMonthMapCache,
cloneTime,
getDateWithTimezone,
getDaysInMonth,
getHourIn12Hour,
} from '../utils/dayjs'
import { import {
PortalToFollowElem, PortalToFollowElem,
PortalToFollowElemContent, PortalToFollowElemContent,
@ -23,6 +29,7 @@ import { useAppContext } from '@/context/app-context'
const DatePicker = ({ const DatePicker = ({
value, value,
timezone,
onChange, onChange,
onClear, onClear,
placeholder, placeholder,
@ -37,12 +44,15 @@ const DatePicker = ({
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
const [view, setView] = useState(ViewType.date) const [view, setView] = useState(ViewType.date)
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const isInitial = useRef(true)
const inputValue = useRef(value ? value.tz(timezone) : undefined).current
const defaultValue = useRef(getDateWithTimezone({ timezone })).current
const [currentDate, setCurrentDate] = useState(value || dayjs()) const [currentDate, setCurrentDate] = useState(inputValue || defaultValue)
const [selectedDate, setSelectedDate] = useState(value) const [selectedDate, setSelectedDate] = useState(inputValue)
const [selectedMonth, setSelectedMonth] = useState((value || dayjs()).month()) const [selectedMonth, setSelectedMonth] = useState((inputValue || defaultValue).month())
const [selectedYear, setSelectedYear] = useState((value || dayjs()).year()) const [selectedYear, setSelectedYear] = useState((inputValue || defaultValue).year())
useEffect(() => { useEffect(() => {
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
@ -55,6 +65,25 @@ const DatePicker = ({
return () => document.removeEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside)
}, []) }, [])
useEffect(() => {
if (isInitial.current) {
isInitial.current = false
return
}
clearMonthMapCache()
if (value) {
const newValue = getDateWithTimezone({ date: value, timezone })
setCurrentDate(newValue)
setSelectedDate(newValue)
onChange(newValue)
}
else {
setCurrentDate(prev => getDateWithTimezone({ date: prev, timezone }))
setSelectedDate(prev => prev ? getDateWithTimezone({ date: prev, timezone }) : undefined)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [timezone])
const handleClickTrigger = (e: React.MouseEvent) => { const handleClickTrigger = (e: React.MouseEvent) => {
e.stopPropagation() e.stopPropagation()
if (isOpen) { if (isOpen) {
@ -63,15 +92,15 @@ const DatePicker = ({
} }
setView(ViewType.date) setView(ViewType.date)
setIsOpen(true) setIsOpen(true)
if (value) {
setCurrentDate(value)
setSelectedDate(value)
}
} }
const handleClear = (e: React.MouseEvent) => { const handleClear = (e: React.MouseEvent) => {
const newDate = dayjs()
e.stopPropagation() e.stopPropagation()
setSelectedDate(undefined) setSelectedDate(undefined)
setCurrentDate(prev => prev || newDate)
setSelectedMonth(prev => prev || newDate.month())
setSelectedYear(prev => prev || newDate.year())
if (!isOpen) if (!isOpen)
onClear() onClear()
} }
@ -89,13 +118,13 @@ const DatePicker = ({
}, [currentDate]) }, [currentDate])
const handleDateSelect = useCallback((day: Dayjs) => { const handleDateSelect = useCallback((day: Dayjs) => {
const newDate = cloneTime(day, selectedDate || dayjs()) const newDate = cloneTime(day, selectedDate || getDateWithTimezone({ timezone }))
setCurrentDate(newDate) setCurrentDate(newDate)
setSelectedDate(newDate) setSelectedDate(newDate)
}, [selectedDate]) }, [selectedDate, timezone])
const handleSelectCurrentDate = () => { const handleSelectCurrentDate = () => {
const newDate = dayjs() const newDate = getDateWithTimezone({ timezone })
setCurrentDate(newDate) setCurrentDate(newDate)
setSelectedDate(newDate) setSelectedDate(newDate)
onChange(newDate) onChange(newDate)
@ -126,19 +155,19 @@ const DatePicker = ({
} }
const handleSelectHour = useCallback((hour: string) => { const handleSelectHour = useCallback((hour: string) => {
const selectedTime = selectedDate || dayjs() const selectedTime = selectedDate || getDateWithTimezone({ timezone })
handleTimeSelect(hour, selectedTime.minute().toString().padStart(2, '0'), selectedTime.format('A') as Period) handleTimeSelect(hour, selectedTime.minute().toString().padStart(2, '0'), selectedTime.format('A') as Period)
}, [selectedDate]) }, [selectedDate, timezone])
const handleSelectMinute = useCallback((minute: string) => { const handleSelectMinute = useCallback((minute: string) => {
const selectedTime = selectedDate || dayjs() const selectedTime = selectedDate || getDateWithTimezone({ timezone })
handleTimeSelect(getHourIn12Hour(selectedTime).toString().padStart(2, '0'), minute, selectedTime.format('A') as Period) handleTimeSelect(getHourIn12Hour(selectedTime).toString().padStart(2, '0'), minute, selectedTime.format('A') as Period)
}, [selectedDate]) }, [selectedDate, timezone])
const handleSelectPeriod = useCallback((period: Period) => { const handleSelectPeriod = useCallback((period: Period) => {
const selectedTime = selectedDate || dayjs() const selectedTime = selectedDate || getDateWithTimezone({ timezone })
handleTimeSelect(getHourIn12Hour(selectedTime).toString().padStart(2, '0'), selectedTime.minute().toString().padStart(2, '0'), period) handleTimeSelect(getHourIn12Hour(selectedTime).toString().padStart(2, '0'), selectedTime.minute().toString().padStart(2, '0'), period)
}, [selectedDate]) }, [selectedDate, timezone])
const handleOpenYearMonthPicker = () => { const handleOpenYearMonthPicker = () => {
setSelectedMonth(currentDate.month()) setSelectedMonth(currentDate.month())
@ -163,15 +192,13 @@ const DatePicker = ({
}, []) }, [])
const handleYearMonthConfirm = () => { const handleYearMonthConfirm = () => {
setCurrentDate((prev) => { setCurrentDate(prev => prev.clone().month(selectedMonth).year(selectedYear))
return prev ? prev.clone().month(selectedMonth).year(selectedYear) : dayjs().month(selectedMonth).year(selectedYear)
})
setView(ViewType.date) setView(ViewType.date)
} }
const timeFormat = needTimePicker ? 'MMMM D, YYYY hh:mm A' : 'MMMM D, YYYY' const timeFormat = needTimePicker ? 'MMMM D, YYYY hh:mm A' : 'MMMM D, YYYY'
const displayValue = value?.format(timeFormat) || '' const displayValue = value?.format(timeFormat) || ''
const displayTime = (selectedDate || dayjs().startOf('day')).format('hh:mm A') const displayTime = selectedDate?.format('hh:mm A') || '--:-- --'
const placeholderDate = isOpen && selectedDate ? selectedDate.format(timeFormat) : (placeholder || t('time.defaultPlaceholder')) const placeholderDate = isOpen && selectedDate ? selectedDate.format(timeFormat) : (placeholder || t('time.defaultPlaceholder'))
return ( return (

View File

@ -1,4 +1,4 @@
import dayjs from 'dayjs' import dayjs from './utils/dayjs'
import { Period } from './types' import { Period } from './types'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'

View File

@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useRef, useState } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react'
import dayjs from 'dayjs'
import type { Period, TimePickerProps } from '../types' import type { Period, TimePickerProps } from '../types'
import { cloneTime, getHourIn12Hour } from '../utils' import dayjs, { cloneTime, getDateWithTimezone, getHourIn12Hour } from '../utils/dayjs'
import { import {
PortalToFollowElem, PortalToFollowElem,
PortalToFollowElemContent, PortalToFollowElemContent,
@ -16,6 +15,7 @@ import cn from '@/utils/classnames'
const TimePicker = ({ const TimePicker = ({
value, value,
timezone,
placeholder, placeholder,
onChange, onChange,
onClear, onClear,
@ -24,7 +24,8 @@ const TimePicker = ({
const { t } = useTranslation() const { t } = useTranslation()
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const [selectedTime, setSelectedTime] = useState(value) const isInitial = useRef(true)
const [selectedTime, setSelectedTime] = useState(value ? getDateWithTimezone({ timezone, date: value }) : undefined)
useEffect(() => { useEffect(() => {
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
@ -35,6 +36,22 @@ const TimePicker = ({
return () => document.removeEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside)
}, []) }, [])
useEffect(() => {
if (isInitial.current) {
isInitial.current = false
return
}
if (value) {
const newValue = getDateWithTimezone({ date: value, timezone })
setSelectedTime(newValue)
onChange(newValue)
}
else {
setSelectedTime(prev => prev ? getDateWithTimezone({ date: prev, timezone }) : undefined)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [timezone])
const handleClickTrigger = (e: React.MouseEvent) => { const handleClickTrigger = (e: React.MouseEvent) => {
e.stopPropagation() e.stopPropagation()
if (isOpen) { if (isOpen) {
@ -42,6 +59,8 @@ const TimePicker = ({
return return
} }
setIsOpen(true) setIsOpen(true)
if (value)
setSelectedTime(value)
} }
const handleClear = (e: React.MouseEvent) => { const handleClear = (e: React.MouseEvent) => {
@ -74,11 +93,11 @@ const TimePicker = ({
}, [selectedTime]) }, [selectedTime])
const handleSelectCurrentTime = useCallback(() => { const handleSelectCurrentTime = useCallback(() => {
const newDate = dayjs() const newDate = getDateWithTimezone({ timezone })
setSelectedTime(newDate) setSelectedTime(newDate)
onChange(newDate) onChange(newDate)
setIsOpen(false) setIsOpen(false)
}, [onChange]) }, [onChange, timezone])
const handleConfirm = useCallback(() => { const handleConfirm = useCallback(() => {
onChange(selectedTime) onChange(selectedTime)

View File

@ -21,6 +21,7 @@ export type TriggerProps = {
export type DatePickerProps = { export type DatePickerProps = {
value: Dayjs | undefined value: Dayjs | undefined
timezone?: string
placeholder?: string placeholder?: string
needTimePicker?: boolean needTimePicker?: boolean
onChange: (date: Dayjs | undefined) => void onChange: (date: Dayjs | undefined) => void
@ -48,6 +49,7 @@ export type DatePickerFooterProps = {
export type TimePickerProps = { export type TimePickerProps = {
value: Dayjs | undefined value: Dayjs | undefined
timezone?: string
placeholder?: string placeholder?: string
onChange: (date: Dayjs | undefined) => void onChange: (date: Dayjs | undefined) => void
onClear: () => void onClear: () => void

View File

@ -1,5 +1,12 @@
import type { Dayjs } from 'dayjs' import dayjs, { type Dayjs } from 'dayjs'
import type { Day } from './types' import type { Day } from '../types'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
export default dayjs
const monthMaps: Record<string, Day[]> = {} const monthMaps: Record<string, Day[]> = {}
@ -58,7 +65,16 @@ export const getDaysInMonth = (currentDate: Dayjs) => {
return days return days
} }
export const clearMonthMapCache = () => {
for (const key in monthMaps)
delete monthMaps[key]
}
export const getHourIn12Hour = (date: Dayjs) => { export const getHourIn12Hour = (date: Dayjs) => {
const hour = date.hour() const hour = date.hour()
return hour === 0 ? 12 : hour >= 12 ? hour - 12 : hour return hour === 0 ? 12 : hour >= 12 ? hour - 12 : hour
} }
export const getDateWithTimezone = (props: { date?: Dayjs, timezone?: string }) => {
return props.date ? dayjs.tz(props.date, props.timezone) : dayjs().tz(props.timezone)
}

View File

@ -239,7 +239,7 @@ const Link = ({ node, ...props }: any) => {
} }
} }
export function Markdown(props: { content: string; className?: string }) { export function Markdown(props: { content: string; className?: string; customDisallowedElements?: string[] }) {
const latexContent = flow([ const latexContent = flow([
preprocessThinkTag, preprocessThinkTag,
preprocessLaTeX, preprocessLaTeX,
@ -274,7 +274,7 @@ export function Markdown(props: { content: string; className?: string }) {
} }
}, },
]} ]}
disallowedElements={['iframe', 'head', 'html', 'meta', 'link', 'style', 'body', 'input']} disallowedElements={['iframe', 'head', 'html', 'meta', 'link', 'style', 'body', ...(props.customDisallowedElements || [])]}
components={{ components={{
code: CodeBlock, code: CodeBlock,
img: Img, img: Img,

View File

@ -22,7 +22,6 @@ type Props = {
} }
const KeyValue = ({ icon, label, tooltip }: { icon: ReactNode; label: string; tooltip?: ReactNode }) => { const KeyValue = ({ icon, label, tooltip }: { icon: ReactNode; label: string; tooltip?: ReactNode }) => {
console.log(label)
return ( return (
<div className='flex text-text-tertiary'> <div className='flex text-text-tertiary'>
<div className='size-4 flex items-center justify-center'> <div className='size-4 flex items-center justify-center'>

View File

@ -181,6 +181,7 @@ const ChunkContent: FC<IChunkContentProps> = ({
<Markdown <Markdown
className='h-full w-full !text-text-secondary' className='h-full w-full !text-text-secondary'
content={question} content={question}
customDisallowedElements={['input']}
/> />
) )
} }

View File

@ -50,6 +50,7 @@ const ChunkContent: FC<ChunkContentProps> = ({
className, className,
)} )}
content={sign_content || content || ''} content={sign_content || content || ''}
customDisallowedElements={['input']}
/> />
} }

View File

@ -60,6 +60,7 @@ const ChunkDetailModal: FC<Props> = ({
<Markdown <Markdown
className={cn('!mt-2 !text-text-secondary', heighClassName)} className={cn('!mt-2 !text-text-secondary', heighClassName)}
content={sign_content || content} content={sign_content || content}
customDisallowedElements={['input']}
/> />
{!isParentChildRetrieval && keywords && keywords.length > 0 && ( {!isParentChildRetrieval && keywords && keywords.length > 0 && (
<div className='mt-6'> <div className='mt-6'>

View File

@ -47,7 +47,11 @@ const ResultItem: FC<Props> = ({
{/* Main */} {/* Main */}
<div className='mt-1 px-3'> <div className='mt-1 px-3'>
<Markdown className='line-clamp-2' content={sign_content || content} /> <Markdown
className='line-clamp-2'
content={sign_content || content}
customDisallowedElements={['input']}
/>
{isParentChildRetrieval && ( {isParentChildRetrieval && (
<div className='mt-1'> <div className='mt-1'>
<div <div

View File

@ -9,7 +9,6 @@ import cn from '@/utils/classnames'
import type { TriggerProps } from '@/app/components/base/date-and-time-picker/types' import type { TriggerProps } from '@/app/components/base/date-and-time-picker/types'
import useTimestamp from '@/hooks/use-timestamp' import useTimestamp from '@/hooks/use-timestamp'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useAppContext } from '@/context/app-context'
type Props = { type Props = {
className?: string className?: string
@ -22,12 +21,12 @@ const WrappedDatePicker = ({
onChange, onChange,
}: Props) => { }: Props) => {
const { t } = useTranslation() const { t } = useTranslation()
const { userProfile: { timezone } } = useAppContext() // const { userProfile: { timezone } } = useAppContext()
const { formatTime: formatTimestamp } = useTimestamp() const { formatTime: formatTimestamp } = useTimestamp()
const handleDateChange = useCallback((date?: dayjs.Dayjs) => { const handleDateChange = useCallback((date?: dayjs.Dayjs) => {
if (date) if (date)
onChange(date.valueOf()) onChange(date.unix())
else else
onChange(null) onChange(null)
}, [onChange]) }, [onChange])
@ -43,7 +42,7 @@ const WrappedDatePicker = ({
value ? 'text-text-secondary' : 'text-text-tertiary', value ? 'text-text-secondary' : 'text-text-tertiary',
)} )}
> >
{value ? formatTimestamp(dayjs.utc(value).tz(timezone).valueOf() / 1000, t('datasetDocuments.metadata.dateTimeFormat')) : 'Choose a time...'} {value ? formatTimestamp(value, t('datasetDocuments.metadata.dateTimeFormat')) : t('dataset.metadata.chooseTime')}
</div> </div>
<RiCloseCircleFill <RiCloseCircleFill
className={cn( className={cn(
@ -60,11 +59,11 @@ const WrappedDatePicker = ({
/> />
</div> </div>
) )
}, [className, value, handleDateChange]) }, [className, value, formatTimestamp, t, handleDateChange])
return ( return (
<DatePicker <DatePicker
value={dayjs(value || Date.now())} value={dayjs(value ? value * 1000 : Date.now())}
onChange={handleDateChange} onChange={handleDateChange}
onClear={handleDateChange} onClear={handleDateChange}
renderTrigger={renderTrigger} renderTrigger={renderTrigger}

View File

@ -2,7 +2,7 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { type MetadataItemWithValue, isShowManageMetadataLocalStorageKey } from '../types' import { DataType, type MetadataItemWithValue, isShowManageMetadataLocalStorageKey } from '../types'
import Field from './field' import Field from './field'
import InputCombined from '../edit-metadata-batch/input-combined' import InputCombined from '../edit-metadata-batch/input-combined'
import { RiDeleteBinLine, RiQuestionLine } from '@remixicon/react' import { RiDeleteBinLine, RiQuestionLine } from '@remixicon/react'
@ -11,6 +11,8 @@ import cn from '@/utils/classnames'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import SelectMetadataModal from '../metadata-dataset/select-metadata-modal' import SelectMetadataModal from '../metadata-dataset/select-metadata-modal'
import AddMetadataButton from '../add-metadata-button' import AddMetadataButton from '../add-metadata-button'
import useTimestamp from '@/hooks/use-timestamp'
import { useTranslation } from 'react-i18next'
type Props = { type Props = {
dataSetId: string dataSetId: string
@ -46,6 +48,9 @@ const InfoGroup: FC<Props> = ({
onAdd, onAdd,
}) => { }) => {
const router = useRouter() const router = useRouter()
const { t } = useTranslation()
const { formatTime: formatTimestamp } = useTimestamp()
const handleMangeMetadata = () => { const handleMangeMetadata = () => {
localStorage.setItem(isShowManageMetadataLocalStorageKey, 'true') localStorage.setItem(isShowManageMetadataLocalStorageKey, 'true')
router.push(`/datasets/${dataSetId}/documents`) router.push(`/datasets/${dataSetId}/documents`)
@ -96,7 +101,7 @@ const InfoGroup: FC<Props> = ({
<RiDeleteBinLine className='size-4' onClick={() => onDelete?.(item)} /> <RiDeleteBinLine className='size-4' onClick={() => onDelete?.(item)} />
</div> </div>
</div> </div>
) : (<div className='py-1 system-xs-regular text-text-secondary'>{item.value}</div>)} ) : (<div className='py-1 system-xs-regular text-text-secondary'>{(item.value && item.type === DataType.time) ? formatTimestamp((item.value as number), t('datasetDocuments.metadata.dateTimeFormat')) : item.value}</div>)}
</Field> </Field>
))} ))}
</div> </div>

View File

@ -73,6 +73,7 @@ const ConditionDate = ({
return ( return (
<div className='px-2 py-1 h-8'> <div className='px-2 py-1 h-8'>
<DatePicker <DatePicker
timezone={timezone}
value={value ? dayjs(value * 1000) : undefined} value={value ? dayjs(value * 1000) : undefined}
onChange={handleDateChange} onChange={handleDateChange}
onClear={handleDateChange} onClear={handleDateChange}

View File

@ -127,7 +127,7 @@ const ConditionItem = ({
<div className='mx-1 w-[1px] h-3 bg-divider-regular'></div> <div className='mx-1 w-[1px] h-3 bg-divider-regular'></div>
<ConditionOperator <ConditionOperator
disabled={!canChooseOperator} disabled={!canChooseOperator}
variableType={currentMetadata!.type} variableType={currentMetadata?.type || MetadataFilteringVariableType.string}
value={condition.comparison_operator} value={condition.comparison_operator}
onSelect={handleConditionOperatorChange} onSelect={handleConditionOperatorChange}
/> />

View File

@ -171,6 +171,7 @@ const translation = {
metadata: { metadata: {
metadata: 'Metadata', metadata: 'Metadata',
addMetadata: 'Add Metadata', addMetadata: 'Add Metadata',
chooseTime: 'Choose a time...',
createMetadata: { createMetadata: {
title: 'New Metadata', title: 'New Metadata',
back: 'Back', back: 'Back',

View File

@ -171,6 +171,7 @@ const translation = {
metadata: { metadata: {
metadata: '元数据', metadata: '元数据',
addMetadata: '添加元数据', addMetadata: '添加元数据',
chooseTime: '选择时间',
createMetadata: { createMetadata: {
title: '新建元数据', title: '新建元数据',
back: '返回', back: '返回',