fix(web): remote file upload

This commit is contained in:
JzoNg 2026-05-09 10:36:16 +08:00
parent e9070daaaa
commit 07fea50216
4 changed files with 54 additions and 17 deletions

View File

@ -248,6 +248,13 @@ describe('Operation', () => {
expect(screen.getByTestId('log-btn'))!.toBeInTheDocument()
})
it('should keep hover-only controls visible when a descendant popup is open', () => {
renderOperation({ ...baseProps, showPromptLog: true })
expect(screen.getByTestId('operation-actions')).toHaveClass('group-has-[[data-popup-open]]:flex')
expect(screen.getByTestId('log-btn').parentElement).toHaveClass('group-has-[[data-popup-open]]:block')
})
it('should not show prompt log for opening statements', () => {
const item = { ...baseItem, isOpeningStatement: true }
renderOperation({ ...baseProps, item, showPromptLog: true })

View File

@ -41,6 +41,8 @@ type FeedbackTooltipProps = {
}
const feedbackTooltipClassName = 'max-w-[260px]'
const answerActiveFlexClassName = 'group-hover:flex group-has-[[data-popup-open]]:flex'
const answerActiveBlockClassName = 'group-hover:block group-has-[[data-popup-open]]:block'
const FeedbackTooltip = ({ content, children }: FeedbackTooltipProps) => {
return (
@ -199,7 +201,7 @@ function Operation({
{shouldShowUserFeedbackBar && !humanInputFormDataList?.length && (
<div className={cn(
'ml-1 items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-xs',
hasUserFeedback ? 'flex' : 'hidden group-hover:flex',
hasUserFeedback ? 'flex' : `hidden ${answerActiveFlexClassName}`,
)}
>
{hasUserFeedback
@ -241,7 +243,7 @@ function Operation({
{shouldShowAdminFeedbackBar && !humanInputFormDataList?.length && (
<div className={cn(
'ml-1 items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-xs',
(hasAdminFeedback || hasUserFeedback) ? 'flex' : 'hidden group-hover:flex',
(hasAdminFeedback || hasUserFeedback) ? 'flex' : `hidden ${answerActiveFlexClassName}`,
)}
>
{displayUserFeedback?.rating && (
@ -308,12 +310,12 @@ function Operation({
</div>
)}
{showPromptLog && !isOpeningStatement && (
<div className="hidden group-hover:block">
<div className={cn('hidden', answerActiveBlockClassName)}>
<Log logItem={item} />
</div>
)}
{!isOpeningStatement && (
<div className="ml-1 hidden items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-xs group-hover:flex" data-testid="operation-actions">
<div className={cn('ml-1 hidden items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-xs', answerActiveFlexClassName)} data-testid="operation-actions">
{(config?.text_to_speech?.enabled && !humanInputFormDataList?.length) && (
<NewAudioButton
id={id}

View File

@ -164,6 +164,29 @@ describe('FileUploaderInAttachmentWrapper', () => {
expect(linkButton.closest('button')).toBeInTheDocument()
})
it('should keep upload button layout stable when remote_url popup opens', () => {
render(
<FileUploaderInAttachmentWrapper
onChange={vi.fn()}
fileConfig={createFileConfig()}
/>,
)
const localButton = screen.getByText(/fileUploader\.uploadFromComputer/).closest('button')
const linkButton = screen.getByText(/fileUploader\.pasteFileLink/).closest('button')
const uploadGroup = localButton?.parentElement?.parentElement
expect(uploadGroup?.children).toHaveLength(2)
fireEvent.click(linkButton!)
expect(uploadGroup?.children).toHaveLength(2)
expect(linkButton).toHaveAttribute('data-popup-open')
expect(localButton?.parentElement).toHaveClass('min-w-0', 'flex-1')
expect(linkButton?.parentElement).toHaveClass('min-w-0', 'flex-1')
expect(linkButton).toHaveClass('w-full', 'min-w-0')
})
it('should disable upload buttons when file limit is reached', () => {
const files = [
createFile({ id: 'f1' }),

View File

@ -55,13 +55,12 @@ const FileUploaderInAttachment = ({
const renderButton = useCallback((option: Option, open?: boolean) => {
return (
<Button
key={option.value}
variant="tertiary"
className={cn('relative grow', open && 'bg-components-button-tertiary-bg-hover')}
className={cn('relative w-full min-w-0', open && 'bg-components-button-tertiary-bg-hover')}
disabled={!!(fileConfig.number_limits && files.length >= fileConfig.number_limits)}
>
{option.icon}
<span className="ml-1">{option.label}</span>
<span className="shrink-0">{option.icon}</span>
<span className="ml-1 min-w-0 truncate">{option.label}</span>
{
option.value === TransferMethod.local_file && (
<FileInput fileConfig={fileConfig} />
@ -74,17 +73,23 @@ const FileUploaderInAttachment = ({
return (open: boolean) => renderButton(option, open)
}, [renderButton])
const renderOption = useCallback((option: Option) => {
if (option.value === TransferMethod.local_file && fileConfig?.allowed_file_upload_methods?.includes(TransferMethod.local_file))
return renderButton(option)
if (option.value === TransferMethod.local_file && fileConfig?.allowed_file_upload_methods?.includes(TransferMethod.local_file)) {
return (
<div key={option.value} className="min-w-0 flex-1">
{renderButton(option)}
</div>
)
}
if (option.value === TransferMethod.remote_url && fileConfig?.allowed_file_upload_methods?.includes(TransferMethod.remote_url)) {
return (
<FileFromLinkOrLocal
key={option.value}
showFromLocal={false}
trigger={renderTrigger(option)}
fileConfig={fileConfig}
/>
<div key={option.value} className="min-w-0 flex-1">
<FileFromLinkOrLocal
showFromLocal={false}
trigger={renderTrigger(option)}
fileConfig={fileConfig}
/>
</div>
)
}
}, [renderButton, renderTrigger, fileConfig])
@ -92,7 +97,7 @@ const FileUploaderInAttachment = ({
return (
<div>
{!isDisabled && (
<div className="flex items-center space-x-1">
<div className="flex items-center gap-1">
{options.map(renderOption)}
</div>
)}