1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-09 10:50:24 +00:00

optimize_file_details (#6868)

* optimize_file_details

* feat: optimize ui

* feat: optimize ui

* feat: optimize ui

---------

Co-authored-by: zheng.shen <zheng.shen@seafile.com>
Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
shenzheng-1
2024-10-12 21:09:57 +08:00
committed by GitHub
parent 3cdb6260e1
commit df29823634
11 changed files with 262 additions and 19 deletions

View File

@@ -0,0 +1,55 @@
.file-details-collapse {
display: flex;
flex-direction: column;
width: 100%;
height: auto;
margin-bottom: 10px;
}
.file-details-collapse .file-details-collapse-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
height: 28px;
width: 100%;
border-radius: 3px;
border: 1px solid rgba(69, 170, 242, 0);
}
.file-details-collapse .file-details-collapse-header:hover {
background-color: #F0F0F0;
}
.file-details-collapse .file-details-collapse-header .file-details-collapse-header-title {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: default;
color: #666;
font-size: 14px;
}
.file-details-collapse .file-details-collapse-header .file-details-collapse-header-operation {
height: 20px;
width: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-left: 4px;
}
.file-details-collapse .file-details-collapse-header .file-details-collapse-header-operation:hover {
background-color: #DBDBDB;
cursor: pointer;
border-radius: 3px;
}
.file-details-collapse .file-details-collapse-header .sf3-font-down {
color: #666666;
}
.file-details-collapse .file-details-collapse-body {
padding: 0 4px;
}

View File

@@ -0,0 +1,38 @@
import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import './index.css';
const Collapse = ({ className, title, children, isCollapse = true }) => {
const [showChildren, setShowChildren] = useState(isCollapse);
const toggleShowChildren = useCallback(() => {
setShowChildren(!showChildren);
}, [showChildren]);
return (
<div className={classnames('file-details-collapse', className)}>
<div className="file-details-collapse-header">
<div className="file-details-collapse-header-title">{title}</div>
<div className="file-details-collapse-header-operation" onClick={toggleShowChildren}>
<i className={`sf3-font sf3-font-down ${showChildren ? '' : 'rotate-90'}`}></i>
</div>
</div>
{showChildren && (
<div className="file-details-collapse-body">
{children}
</div>
)}
</div>
);
};
Collapse.propTypes = {
isCollapse: PropTypes.bool,
className: PropTypes.string,
title: PropTypes.string,
children: PropTypes.any,
};
export default Collapse;

View File

@@ -0,0 +1,20 @@
.sf-metadata-property-detail-capture-information-item .dirent-detail-item-name {
font-size: 12px;
min-height: 24px;
padding: 3px 6px;
word-break: break-all;
}
.sf-metadata-property-detail-capture-information-item .dirent-detail-item-value {
font-size: 12px;
min-height: 24px;
padding: 3px 6px;
display: block;
word-break: break-all;
}
.sf-metadata-property-detail-capture-information-item .dirent-detail-item-value:empty::before {
content: attr(placeholder);
color: #666;
font-size: 12px;
}

View File

@@ -3,19 +3,65 @@ import PropTypes from 'prop-types';
import { v4 as uuidV4 } from 'uuid';
import { Formatter } from '@seafile/sf-metadata-ui-component';
import classnames from 'classnames';
import { getDirentPath } from './utils';
import DetailItem from '../detail-item';
import { CellType } from '../../../metadata/constants';
import { gettext } from '../../../utils/constants';
import EditFileTagPopover from '../../popover/edit-filetag-popover';
import FileTagList from '../../file-tag-list';
import { Utils } from '../../../utils/utils';
import { MetadataDetails, useMetadata } from '../../../metadata';
import ObjectUtils from '../../../metadata/utils/object-utils';
import { getDirentPath } from '../utils';
import DetailItem from '../../detail-item';
import { CellType, GEOLOCATION_FORMAT, PRIVATE_COLUMN_KEY } from '../../../../metadata/constants';
import { gettext } from '../../../../utils/constants';
import EditFileTagPopover from '../../../popover/edit-filetag-popover';
import FileTagList from '../../../file-tag-list';
import { Utils } from '../../../../utils/utils';
import { MetadataDetails, useMetadata } from '../../../../metadata';
import ObjectUtils from '../../../../metadata/utils/object-utils';
import { getCellValueByColumn, getDateDisplayString, getGeolocationDisplayString,
decimalToExposureTime,
} from '../../../../metadata/utils/cell';
import Collapse from './collapse';
import './index.css';
const getImageInfoName = (key) => {
switch (key) {
case 'Dimensions':
return gettext('Dimensions');
case 'Device make':
return gettext('Device make');
case 'Device model':
return gettext('Device model');
case 'Color space':
return gettext('Color space');
case 'Capture time':
return gettext('Capture time');
case 'Focal length':
return gettext('Focal length');
case 'F number':
return gettext('F number');
case 'Exposure time':
return gettext('Exposure time');
default:
return key;
}
};
const getImageInfoValue = (key, value) => {
if (!value) return value;
switch (key) {
case 'Dimensions':
return value.replace('x', ' x ');
case 'Capture time':
return getDateDisplayString(value, 'YYYY-MM-DD HH:mm:ss');
case 'Focal length':
return value.replace('mm', ' ' + gettext('mm'));
case 'Exposure time':
return decimalToExposureTime(value) + ' ' + gettext('s');
default:
return value;
}
};
const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail, onFileTagChanged, repoTags, fileTagList }) => {
const [isEditFileTagShow, setEditFileTagShow] = useState(false);
const { enableMetadata } = useMetadata();
const [record, setRecord] = useState(null);
const direntPath = useMemo(() => getDirentPath(dirent, path), [dirent, path]);
const tagListTitleID = useMemo(() => `detail-list-view-tags-${uuidV4()}`, []);
@@ -32,7 +78,11 @@ const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail,
onFileTagChanged(dirent, direntPath);
}, [dirent, direntPath, onFileTagChanged]);
return (
const updateRecord = useCallback((record) => {
setRecord(record);
}, []);
const dom = (
<>
<DetailItem field={sizeField} className="sf-metadata-property-detail-formatter">
<Formatter field={sizeField} value={Utils.bytesToSize(direntDetail.size)} />
@@ -68,8 +118,47 @@ const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail,
</DetailItem>
)}
{window.app.pageOptions.enableMetadataManagement && enableMetadata && (
<MetadataDetails repoID={repoID} filePath={direntPath} repoInfo={repoInfo} direntType="file" />
<MetadataDetails repoID={repoID} filePath={direntPath} repoInfo={repoInfo} direntType="file" updateRecord={updateRecord} />
)}
</>
);
let component = dom;
if (Utils.imageCheck(dirent.name)) {
const fileDetails = getCellValueByColumn(record, { key: PRIVATE_COLUMN_KEY.FILE_DETAILS });
const fileDetailsJson = JSON.parse(fileDetails?.slice(9, -7) || '{}');
const fileLocation = getCellValueByColumn(record, { key: PRIVATE_COLUMN_KEY.LOCATION });
component = (
<>
<Collapse title={gettext('General information')}>
{dom}
</Collapse>
<Collapse title={gettext('Capture information')}>
{Object.entries(fileDetailsJson).map(item => {
return (
<div className="dirent-detail-item sf-metadata-property-detail-capture-information-item" key={item[0]}>
<div className="dirent-detail-item-name">{getImageInfoName(item[0])}</div>
<div className="dirent-detail-item-value" placeholder={gettext('Empty')}>{getImageInfoValue(item[0], item[1])}</div>
</div>
);
})}
{fileLocation && (
<div className="dirent-detail-item sf-metadata-property-detail-capture-information-item" key={'location'}>
<div className="dirent-detail-item-name">{gettext('Location')}</div>
<div className="dirent-detail-item-value" placeholder={gettext('Empty')}>
{getGeolocationDisplayString(fileLocation, { geo_format: GEOLOCATION_FORMAT.LNG_LAT })}
</div>
</div>
)}
</Collapse>
</>
);
}
return (
<>
{component}
{isEditFileTagShow &&
<EditFileTagPopover
repoID={repoID}

View File

@@ -45,7 +45,7 @@ const TreeSection = ({ title, children, moreKey, moreOperations, moreOperationCl
}, []);
return (
<div className={classnames('tree-section', { [className]: className })}>
<div className={classnames('tree-section', className)}>
<div
className={classnames('tree-section-header', { 'tree-section-header-hover': highlight })}
onMouseEnter={onMouseEnter}