file-item.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import {
  2. memo,
  3. } from 'react'
  4. import {
  5. RiDeleteBinLine,
  6. RiDownloadLine,
  7. } from '@remixicon/react'
  8. import FileTypeIcon from '../file-type-icon'
  9. import {
  10. fileIsUploaded,
  11. getFileAppearanceType,
  12. getFileExtension,
  13. } from '../utils'
  14. import FileImageRender from '../file-image-render'
  15. import type { FileEntity } from '../types'
  16. import ActionButton from '@/app/components/base/action-button'
  17. import ProgressCircle from '@/app/components/base/progress-bar/progress-circle'
  18. import { formatFileSize } from '@/utils/format'
  19. import cn from '@/utils/classnames'
  20. import { ReplayLine } from '@/app/components/base/icons/src/vender/other'
  21. import { SupportUploadFileTypes } from '@/app/components/workflow/types'
  22. type FileInAttachmentItemProps = {
  23. file: FileEntity
  24. showDeleteAction?: boolean
  25. showDownloadAction?: boolean
  26. onRemove?: (fileId: string) => void
  27. onReUpload?: (fileId: string) => void
  28. }
  29. const FileInAttachmentItem = ({
  30. file,
  31. showDeleteAction,
  32. showDownloadAction = true,
  33. onRemove,
  34. onReUpload,
  35. }: FileInAttachmentItemProps) => {
  36. const { id, name, type, progress, supportFileType, base64Url, url, isRemote } = file
  37. const ext = getFileExtension(name, type, isRemote)
  38. const isImageFile = supportFileType === SupportUploadFileTypes.image
  39. return (
  40. <div className={cn(
  41. 'flex items-center pr-3 h-12 rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg shadow-xs',
  42. progress === -1 && 'bg-state-destructive-hover border-state-destructive-border',
  43. )}>
  44. <div className='flex items-center justify-center w-12 h-12'>
  45. {
  46. isImageFile && (
  47. <FileImageRender
  48. className='w-8 h-8'
  49. imageUrl={base64Url || url || ''}
  50. />
  51. )
  52. }
  53. {
  54. !isImageFile && (
  55. <FileTypeIcon
  56. type={getFileAppearanceType(name, type)}
  57. size='lg'
  58. />
  59. )
  60. }
  61. </div>
  62. <div className='grow w-0 mr-1'>
  63. <div
  64. className='flex items-center mb-0.5 system-xs-medium text-text-secondary truncate'
  65. title={file.name}
  66. >
  67. <div className='truncate'>{name}</div>
  68. </div>
  69. <div className='flex items-center system-2xs-medium-uppercase text-text-tertiary'>
  70. {
  71. ext && (
  72. <span>{ext.toLowerCase()}</span>
  73. )
  74. }
  75. {
  76. ext && (
  77. <span className='mx-1 system-2xs-medium'>•</span>
  78. )
  79. }
  80. {
  81. !!file.size && (
  82. <span>{formatFileSize(file.size)}</span>
  83. )
  84. }
  85. </div>
  86. </div>
  87. <div className='shrink-0 flex items-center'>
  88. {
  89. progress >= 0 && !fileIsUploaded(file) && (
  90. <ProgressCircle
  91. className='mr-2.5'
  92. percentage={progress}
  93. />
  94. )
  95. }
  96. {
  97. progress === -1 && (
  98. <ActionButton
  99. className='mr-1'
  100. onClick={() => onReUpload?.(id)}
  101. >
  102. <ReplayLine className='w-4 h-4 text-text-tertiary' />
  103. </ActionButton>
  104. )
  105. }
  106. {
  107. showDeleteAction && (
  108. <ActionButton onClick={() => onRemove?.(id)}>
  109. <RiDeleteBinLine className='w-4 h-4' />
  110. </ActionButton>
  111. )
  112. }
  113. {
  114. showDownloadAction && (
  115. <ActionButton
  116. size='xs'
  117. >
  118. <RiDownloadLine className='w-3.5 h-3.5 text-text-tertiary' />
  119. </ActionButton>
  120. )
  121. }
  122. </div>
  123. </div>
  124. )
  125. }
  126. export default memo(FileInAttachmentItem)