diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b42107cf42..44ce921614 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -19,7 +19,7 @@
"@seafile/sdoc-editor": "1.0.50",
"@seafile/seafile-calendar": "0.0.12",
"@seafile/seafile-editor": "1.0.109",
- "@seafile/sf-metadata-ui-component": "0.0.18",
+ "@seafile/sf-metadata-ui-component": "0.0.20",
"@uiw/codemirror-extensions-langs": "^4.19.4",
"@uiw/react-codemirror": "^4.19.4",
"axios": "^1.7.3",
@@ -5094,9 +5094,9 @@
}
},
"node_modules/@seafile/sf-metadata-ui-component": {
- "version": "0.0.18",
- "resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.18.tgz",
- "integrity": "sha512-jC4JL06dAntWIr/ZPA/zJ4I9NhDfw0ismvSQuGZsBMvdrdbBBGuFVxirohB9zzwzc0k/K2epyQ/1iARKv5wjow==",
+ "version": "0.0.20",
+ "resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.20.tgz",
+ "integrity": "sha512-nCeqHgwAkd05GKd3YROf3k7XEQuh6FicOeYVXcbCXjzH1pki8XxLcv1NW4D85LvWh2eS6m+utegcAlXfS1EsJQ==",
"dependencies": {
"@seafile/seafile-calendar": "0.0.24",
"@seafile/seafile-editor": "~1.0.102",
diff --git a/frontend/package.json b/frontend/package.json
index f1faed46e6..557ab15121 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -14,7 +14,7 @@
"@seafile/sdoc-editor": "1.0.50",
"@seafile/seafile-calendar": "0.0.12",
"@seafile/seafile-editor": "1.0.109",
- "@seafile/sf-metadata-ui-component": "0.0.18",
+ "@seafile/sf-metadata-ui-component": "0.0.20",
"@uiw/codemirror-extensions-langs": "^4.19.4",
"@uiw/react-codemirror": "^4.19.4",
"axios": "^1.7.3",
diff --git a/frontend/src/components/dirent-detail/detail-item/index.css b/frontend/src/components/dirent-detail/detail-item/index.css
index aa5913e65b..21323101be 100644
--- a/frontend/src/components/dirent-detail/detail-item/index.css
+++ b/frontend/src/components/dirent-detail/detail-item/index.css
@@ -12,12 +12,12 @@
.dirent-detail-item .dirent-detail-item-name {
width: 160px;
- padding: 7px 6px;
+ padding: 6.5px 6px;
min-height: 34px;
height: fit-content;
color: #666;
font-size: 14px;
- line-height: 1.4;
+ line-height: 1.5;
}
.dirent-detail-item .dirent-detail-item-name .sf-metadata-icon {
@@ -29,13 +29,8 @@
.dirent-detail-item .dirent-detail-item-value {
width: 200px;
display: flex;
- padding: 7px 6px;
- min-height: 34px;
height: fit-content;
-}
-
-.dirent-detail-item .dirent-detail-item-value.editable:hover {
- cursor: pointer;
+ min-height: 34px;
}
.dirent-detail-item .dirent-detail-item-name:hover,
@@ -45,10 +40,48 @@
cursor: default;
}
+.dirent-detail-item .dirent-detail-item-value.editable:hover {
+ cursor: pointer;
+}
+
+/* media */
+.cur-view-detail-small .dirent-detail-item .dirent-detail-item-name {
+ width: calc((100% - 8px) * 0.44);
+}
+
+.cur-view-detail-small .dirent-detail-item .dirent-detail-item-value {
+ width: calc((100% - 8px) * 0.56);
+}
+
+.cur-view-detail-large .dirent-detail-item .dirent-detail-item-name {
+ width: 160px;
+ margin-right: 8px;
+}
+
+.cur-view-detail-large .dirent-detail-item .dirent-detail-item-value {
+ flex: 1;
+}
+
+.dirent-detail-item .dirent-detail-item-value:not(.editable) .sf-metadata-record-cell-empty {
+ display: inline-block;
+ height: 34px;
+ width: 100%;
+ line-height: 1.5;
+ padding: 6.5px 6px;
+}
+
+.dirent-detail-item .dirent-detail-item-value:not(.editable) .sf-metadata-record-cell-empty:empty::before {
+ content: attr(placeholder);
+ color: #666;
+ font-size: 14px;
+}
+
+/* formatter */
.dirent-detail-item .dirent-detail-item-value .text-formatter,
.dirent-detail-item .dirent-detail-item-value .ctime-formatter,
.dirent-detail-item .dirent-detail-item-value .mtime-formatter,
.dirent-detail-item .dirent-detail-item-value .date-formatter {
+ padding: 6.5px 6px;
line-height: 1.5;
}
@@ -57,28 +90,5 @@
}
.dirent-detail-item-value .creator-formatter {
- height: 20px;
-}
-
-.dirent-detail-item-value .sf-metadata-record-cell-empty::before {
- content: attr(placeholder);
- color: #666;
- font-size: 14px;
-}
-
-/* */
-.cur-view-detail-small .dirent-detail-item .dirent-detail-item-name {
- width: 44%;
-}
-
-.cur-view-detail-small .dirent-detail-item .dirent-detail-item-value {
- width: 56%;
-}
-
-.cur-view-detail-large .dirent-detail-item .dirent-detail-item-name {
- width: 160px;
-}
-
-.cur-view-detail-large .dirent-detail-item .dirent-detail-item-value {
- flex: 1;
+ padding: 7px 6px;
}
diff --git a/frontend/src/components/dirent-detail/detail-item/index.js b/frontend/src/components/dirent-detail/detail-item/index.js
index dcde4e76c7..332b4ca88e 100644
--- a/frontend/src/components/dirent-detail/detail-item/index.js
+++ b/frontend/src/components/dirent-detail/detail-item/index.js
@@ -1,40 +1,39 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
-import { Formatter, Icon } from '@seafile/sf-metadata-ui-component';
import classnames from 'classnames';
+import { Icon } from '@seafile/sf-metadata-ui-component';
import { CellType, COLUMNS_ICON_CONFIG } from '../../../metadata/metadata-view/_basic';
-import { gettext } from '../../../utils/constants';
import './index.css';
-const DetailItem = ({ field, value, valueId, valueClick, children, ...params }) => {
+const DetailItem = ({ readonly, field, className, children }) => {
const icon = useMemo(() => {
if (field.type === 'size') return COLUMNS_ICON_CONFIG[CellType.NUMBER];
return COLUMNS_ICON_CONFIG[field.type];
}, [field]);
return (
-
+
{field.name}
-
- {children ? children : (
)}
+
+ {children}
);
};
DetailItem.defaultProps = {
- emptyTip: gettext('Empty')
+ readonly: true,
};
DetailItem.propTypes = {
+ readonly: PropTypes.bool,
field: PropTypes.object.isRequired,
- value: PropTypes.any,
+ className: PropTypes.string,
children: PropTypes.any,
- valueId: PropTypes.string,
};
export default DetailItem;
diff --git a/frontend/src/components/dirent-detail/dirent-details/dir-details.js b/frontend/src/components/dirent-detail/dirent-details/dir-details.js
index b29554b34a..af390f7cad 100644
--- a/frontend/src/components/dirent-detail/dirent-details/dir-details.js
+++ b/frontend/src/components/dirent-detail/dirent-details/dir-details.js
@@ -1,20 +1,26 @@
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
+import { Formatter } from '@seafile/sf-metadata-ui-component';
import { getDirentPath } from './utils';
import DetailItem from '../detail-item';
import { CellType } from '../../../metadata/metadata-view/_basic';
import { gettext } from '../../../utils/constants';
import { MetadataDetails, useMetadata } from '../../../metadata';
-const DirDetails = ({ repoID, repoInfo, dirent, path, direntDetail, ...params }) => {
+const DirDetails = ({ repoID, repoInfo, dirent, path, direntDetail }) => {
const direntPath = useMemo(() => getDirentPath(dirent, path), [dirent, path]);
const { enableMetadata } = useMetadata();
+ const lastModifiedTimeField = useMemo(() => {
+ return { type: CellType.MTIME, name: gettext('Last modified time') };
+ }, []);
return (
<>
-
+
+
+
{window.app.pageOptions.enableMetadataManagement && enableMetadata && (
-
+
)}
>
);
diff --git a/frontend/src/components/dirent-detail/dirent-details/file-details.js b/frontend/src/components/dirent-detail/dirent-details/file-details.js
index a075a2679f..b00e54072d 100644
--- a/frontend/src/components/dirent-detail/dirent-details/file-details.js
+++ b/frontend/src/components/dirent-detail/dirent-details/file-details.js
@@ -1,6 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { v4 as uuidV4 } from 'uuid';
+import { Formatter } from '@seafile/sf-metadata-ui-component';
import { getDirentPath } from './utils';
import DetailItem from '../detail-item';
import { CellType } from '../../../metadata/metadata-view/_basic';
@@ -11,12 +12,16 @@ import { Utils } from '../../../utils/utils';
import { MetadataDetails, useMetadata } from '../../../metadata';
import ObjectUtils from '../../../metadata/metadata-view/utils/object-utils';
-const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail, onFileTagChanged, repoTags, fileTagList, ...params }) => {
+const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail, onFileTagChanged, repoTags, fileTagList }) => {
const [isEditFileTagShow, setEditFileTagShow] = useState(false);
const { enableMetadata } = useMetadata();
const direntPath = useMemo(() => getDirentPath(dirent, path), [dirent, path]);
const tagListTitleID = useMemo(() => `detail-list-view-tags-${uuidV4()}`, []);
+ const sizeField = useMemo(() => ({ type: 'size', name: gettext('Size') }), []);
+ const lastModifierField = useMemo(() => ({ type: CellType.LAST_MODIFIER, name: gettext('Last modifier') }), []);
+ const lastModifiedTimeField = useMemo(() => ({ type: CellType.MTIME, name: gettext('Last modified time') }), []);
+ const tagsField = useMemo(() => ({ type: CellType.SINGLE_SELECT, name: gettext('Tags') }), []);
const onEditFileTagToggle = useCallback(() => {
setEditFileTagShow(!isEditFileTagShow);
@@ -28,25 +33,37 @@ const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail,
return (
<>
-
-
-
+
+
+
+
+
+
+
+
+
{!window.app.pageOptions.enableMetadataManagement && enableMetadata && (
-
- {Array.isArray(fileTagList) && fileTagList.length > 0 ? (
-
- ) : (
- {gettext('Empty')}
- )}
+
+
+ {Array.isArray(fileTagList) && fileTagList.length > 0 ? (
+
+ ) : (
+ {gettext('Empty')}
+ )}
+
)}
{window.app.pageOptions.enableMetadataManagement && (
-
+
)}
{isEditFileTagShow &&
{
- const newCollaboratorsCache = { ...this.state.collaboratorsCache, [user.email]: user };
- this.setState({ collaboratorsCache: newCollaboratorsCache });
- };
-
- loadCollaborators = () => {
- metadataAPI.getCollaborators(this.props.repoID).then(res => {
- const collaborators = Array.isArray(res?.data?.user_list) ? res.data.user_list.map(user => new User(user)) : [];
- this.setState({ collaborators });
- }).catch(error => {
- this.setState({ collaborators: [] });
- });
- };
-
updateDetail = (repoID, dirent, direntPath) => {
const apiName = dirent.type === 'file' ? 'getFileInfo' : 'getDirInfo';
seafileAPI[apiName](repoID, direntPath).then(res => {
@@ -73,7 +53,6 @@ class DirentDetails extends React.Component {
};
componentDidMount() {
- this.loadCollaborators();
this.loadDetail(this.props.repoID, this.props.dirent, this.props.path);
}
@@ -108,7 +87,7 @@ class DirentDetails extends React.Component {
};
render() {
- const { dirent, direntDetail, collaborators, collaboratorsCache } = this.state;
+ const { dirent, direntDetail } = this.state;
const { repoID, path, fileTags } = this.props;
const direntName = dirent?.name || '';
const smallIconUrl = Utils.getDirentIcon(dirent);
@@ -127,10 +106,6 @@ class DirentDetails extends React.Component {
dirent={dirent}
direntDetail={direntDetail}
path={this.props.dirent ? path + '/' + dirent.name : path}
- collaborators={collaborators}
- collaboratorsCache={collaboratorsCache}
- updateCollaboratorsCache={this.updateCollaboratorsCache}
- queryUserAPI={this.userService?.queryUser}
/>
) : (
)}
diff --git a/frontend/src/components/dirent-detail/index.js b/frontend/src/components/dirent-detail/index.js
index 5703fd0dbc..30a7ab442b 100644
--- a/frontend/src/components/dirent-detail/index.js
+++ b/frontend/src/components/dirent-detail/index.js
@@ -1,11 +1,24 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import LibDetail from './lib-details';
import DirentDetail from './dirent-details';
import ObjectUtils from '../../metadata/metadata-view/utils/object-utils';
+import { MetadataContext } from '../../metadata';
+import { mediaUrl } from '../../utils/constants';
const Index = React.memo(({ repoID, path, dirent, currentRepoInfo, repoTags, fileTags, onClose, onFileTagChanged }) => {
+ useEffect(() => {
+ // init context
+ const context = new MetadataContext();
+ window.sfMetadataContext = context;
+ window.sfMetadataContext.init({ repoID, mediaUrl, repoInfo: currentRepoInfo });
+ return () => {
+ window.sfMetadataContext.destroy();
+ delete window['sfMetadataContext'];
+ };
+ }, [repoID, currentRepoInfo]);
+
if (path === '/' && !dirent) {
return (
diff --git a/frontend/src/components/dirent-detail/lib-details/index.js b/frontend/src/components/dirent-detail/lib-details/index.js
index 794b724759..1539197d93 100644
--- a/frontend/src/components/dirent-detail/lib-details/index.js
+++ b/frontend/src/components/dirent-detail/lib-details/index.js
@@ -1,5 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
+import { Formatter } from '@seafile/sf-metadata-ui-component';
import { Utils } from '../../../utils/utils';
import { gettext } from '../../../utils/constants';
import { seafileAPI } from '../../../utils/seafile-api';
@@ -14,6 +15,10 @@ const LibDetail = React.memo(({ currentRepoInfo, onClose }) => {
const [isLoading, setLoading] = useState(true);
const [repo, setRepo] = useState({});
const smallIconUrl = useMemo(() => Utils.getLibIconUrl(currentRepoInfo), [currentRepoInfo]);
+ const filesField = useMemo(() => ({ type: CellType.NUMBER, name: gettext('Files') }), []);
+ const sizeField = useMemo(() => ({ type: 'size', name: gettext('Size') }), []);
+ const creatorField = useMemo(() => ({ type: CellType.CREATOR, name: gettext('Creator') }), []);
+ const mtimeField = useMemo(() => ({ type: CellType.MTIME, name: gettext('Last modified time') }), []);
useEffect(() => {
setLoading(true);
@@ -35,15 +40,27 @@ const LibDetail = React.memo(({ currentRepoInfo, onClose }) => {
) : (
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
)}