Add Meta Data section to FileInfo component and update file thumbnail fetching logic
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Introduced a new Meta Data section in the FileInfo component, allowing users to view file metadata. - Added a fetchFileThumbnail function in ApiServerContext to retrieve file thumbnails, enhancing the user experience with profile images. - Updated the UserProfileImage component to utilize the new thumbnail fetching logic, improving image loading efficiency. - Added a hasThumbnails property to the File model to indicate the presence of thumbnail data.
This commit is contained in:
parent
ff61cd4f06
commit
9aa2b0f2f8
@ -25,6 +25,9 @@ import FilePreview from '../../common/FilePreview.jsx'
|
|||||||
import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
|
import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
|
||||||
import { ApiServerContext } from '../../context/ApiServerContext.jsx'
|
import { ApiServerContext } from '../../context/ApiServerContext.jsx'
|
||||||
import ScrollBox from '../../common/ScrollBox.jsx'
|
import ScrollBox from '../../common/ScrollBox.jsx'
|
||||||
|
import JsonObjectIcon from '../../../Icons/JsonObjectIcon.jsx'
|
||||||
|
import ObjectProperty from '../../common/ObjectProperty.jsx'
|
||||||
|
import { getModelProperty } from '../../../../database/ObjectModels.js'
|
||||||
|
|
||||||
const log = loglevel.getLogger('FileInfo')
|
const log = loglevel.getLogger('FileInfo')
|
||||||
log.setLevel(config.logLevel)
|
log.setLevel(config.logLevel)
|
||||||
@ -95,6 +98,7 @@ const FileInfo = () => {
|
|||||||
items={[
|
items={[
|
||||||
{ key: 'info', label: 'File Information' },
|
{ key: 'info', label: 'File Information' },
|
||||||
{ key: 'preview', label: 'Preview' },
|
{ key: 'preview', label: 'Preview' },
|
||||||
|
{ key: 'metaData', label: 'Meta Data' },
|
||||||
{ key: 'notes', label: 'Notes' },
|
{ key: 'notes', label: 'Notes' },
|
||||||
{ key: 'auditLogs', label: 'Audit Logs' }
|
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||||
]}
|
]}
|
||||||
@ -131,7 +135,9 @@ const FileInfo = () => {
|
|||||||
}}
|
}}
|
||||||
editLoading={objectFormState.editLoading}
|
editLoading={objectFormState.editLoading}
|
||||||
formValid={objectFormState.formValid}
|
formValid={objectFormState.formValid}
|
||||||
disabled={objectFormState.beingEditedByOther || objectFormState.loading}
|
disabled={
|
||||||
|
objectFormState.beingEditedByOther || objectFormState.loading
|
||||||
|
}
|
||||||
loading={objectFormState.editLoading}
|
loading={objectFormState.editLoading}
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
@ -164,6 +170,8 @@ const FileInfo = () => {
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
type='file'
|
type='file'
|
||||||
|
labelWidth={170}
|
||||||
|
visibleProperties={{ metaData: false }}
|
||||||
objectData={objectData}
|
objectData={objectData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -188,6 +196,24 @@ const FileInfo = () => {
|
|||||||
<MissingPlaceholder message={'No file.'} />
|
<MissingPlaceholder message={'No file.'} />
|
||||||
)}
|
)}
|
||||||
</InfoCollapse>
|
</InfoCollapse>
|
||||||
|
<InfoCollapse
|
||||||
|
title='Meta Data'
|
||||||
|
icon={<JsonObjectIcon />}
|
||||||
|
active={collapseState.metaData}
|
||||||
|
onToggle={(expanded) => updateCollapseState('metaData', expanded)}
|
||||||
|
collapseKey='metaData'
|
||||||
|
>
|
||||||
|
{objectFormState?.objectData?._id ? (
|
||||||
|
<Card>
|
||||||
|
<ObjectProperty
|
||||||
|
{...getModelProperty('file', 'metaData')}
|
||||||
|
objectData={objectFormState?.objectData}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
<MissingPlaceholder message={'No file meta data.'} />
|
||||||
|
)}
|
||||||
|
</InfoCollapse>
|
||||||
<InfoCollapse
|
<InfoCollapse
|
||||||
title='Notes'
|
title='Notes'
|
||||||
icon={<NoteIcon />}
|
icon={<NoteIcon />}
|
||||||
|
|||||||
@ -39,9 +39,9 @@ const UserProfileImage = memo(function UserProfileImage({
|
|||||||
profileImageId,
|
profileImageId,
|
||||||
displayName
|
displayName
|
||||||
}) {
|
}) {
|
||||||
const { fetchFileContent } = useContext(ApiServerContext)
|
const { fetchFileThumbnail } = useContext(ApiServerContext)
|
||||||
const fetchFileContentRef = useRef(fetchFileContent)
|
const fetchFileThumbnailRef = useRef(fetchFileThumbnail)
|
||||||
fetchFileContentRef.current = fetchFileContent
|
fetchFileThumbnailRef.current = fetchFileThumbnail
|
||||||
|
|
||||||
const [profileImageUrl, setProfileImageUrl] = useState(null)
|
const [profileImageUrl, setProfileImageUrl] = useState(null)
|
||||||
const profileImageUrlRef = useRef(null)
|
const profileImageUrlRef = useRef(null)
|
||||||
@ -66,11 +66,11 @@ const UserProfileImage = memo(function UserProfileImage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
const file = { _id: profileImageId, name: '', extension: '' }
|
const file = { _id: profileImageId }
|
||||||
|
|
||||||
const loadProfileImage = async () => {
|
const loadProfileImage = async () => {
|
||||||
try {
|
try {
|
||||||
const fileURL = await fetchFileContentRef.current(file, false)
|
const fileURL = await fetchFileThumbnailRef.current(file, 64)
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
if (profileImageUrlRef.current) {
|
if (profileImageUrlRef.current) {
|
||||||
URL.revokeObjectURL(profileImageUrlRef.current)
|
URL.revokeObjectURL(profileImageUrlRef.current)
|
||||||
|
|||||||
@ -1438,6 +1438,31 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchFileThumbnail = async (file, size) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(
|
||||||
|
`${config.backendUrl}/files/${file._id}/thumbnail`,
|
||||||
|
{
|
||||||
|
params: { size },
|
||||||
|
headers: {
|
||||||
|
Accept: 'image/jpeg',
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
},
|
||||||
|
responseType: 'blob'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const blob = new Blob([response.data], {
|
||||||
|
type: response.headers['content-type'] || 'image/jpeg'
|
||||||
|
})
|
||||||
|
return window.URL.createObjectURL(blob)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
showError(err, () => {
|
||||||
|
fetchFileThumbnail(file, size)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch notes for a specific parent
|
// Fetch notes for a specific parent
|
||||||
const fetchNotes = async (parentId) => {
|
const fetchNotes = async (parentId) => {
|
||||||
logger.debug('Fetching notes for parent:', parentId)
|
logger.debug('Fetching notes for parent:', parentId)
|
||||||
@ -2136,6 +2161,7 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
fetchLoading,
|
fetchLoading,
|
||||||
showError,
|
showError,
|
||||||
fetchFileContent,
|
fetchFileContent,
|
||||||
|
fetchFileThumbnail,
|
||||||
exportToExcel,
|
exportToExcel,
|
||||||
exportToCsv,
|
exportToCsv,
|
||||||
fetchTemplatePreview,
|
fetchTemplatePreview,
|
||||||
|
|||||||
@ -167,6 +167,14 @@ export const File = {
|
|||||||
type: 'data',
|
type: 'data',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
required: false
|
required: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hasThumbnails',
|
||||||
|
label: 'Has Thumbnails',
|
||||||
|
type: 'bool',
|
||||||
|
readOnly: true,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 100
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user