mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-15 07:52:14 +00:00
fix: set width fail (#6509)
* fix: set width fail * feat: update code * feat: update code * feat: update code * feat: update code --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
parent
0921335971
commit
e2bb71e8c9
@ -1,11 +1,8 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import TreeSection from '../tree-section';
|
||||
import { MetadataStatusManagementDialog, MetadataTreeView } from '../../metadata';
|
||||
import metadataAPI from '../../metadata/api';
|
||||
import toaster from '../toast';
|
||||
import { MetadataStatusManagementDialog, MetadataTreeView, useMetadataStatus } from '../../metadata';
|
||||
|
||||
const DirViews = ({ userPerm, repoID, currentPath, onNodeClick }) => {
|
||||
const enableMetadataManagement = useMemo(() => {
|
||||
@ -13,9 +10,8 @@ const DirViews = ({ userPerm, repoID, currentPath, onNodeClick }) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [window.app.pageOptions.enableMetadataManagement]);
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [showMetadataStatusManagementDialog, setShowMetadataStatusManagementDialog] = useState(false);
|
||||
const [metadataStatus, setMetadataStatus] = useState(false);
|
||||
const { enableExtendedProperties, updateEnableExtendedProperties } = useMetadataStatus();
|
||||
const moreOperations = useMemo(() => {
|
||||
if (!enableMetadataManagement) return [];
|
||||
if (userPerm !== 'rw' && userPerm !== 'admin') return [];
|
||||
@ -24,25 +20,6 @@ const DirViews = ({ userPerm, repoID, currentPath, onNodeClick }) => {
|
||||
];
|
||||
}, [enableMetadataManagement, userPerm]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableMetadataManagement) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const repoMetadataManagementEnabledStatusRes = metadataAPI.getMetadataStatus(repoID);
|
||||
Promise.all([repoMetadataManagementEnabledStatusRes]).then(results => {
|
||||
const [repoMetadataManagementEnabledStatusRes] = results;
|
||||
setMetadataStatus(repoMetadataManagementEnabledStatusRes.data.enabled);
|
||||
setLoading(false);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(errorMsg);
|
||||
setLoading(false);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const moreOperationClick = useCallback((operationKey) => {
|
||||
if (operationKey === 'extended-properties') {
|
||||
setShowMetadataStatusManagementDialog(true);
|
||||
@ -55,9 +32,8 @@ const DirViews = ({ userPerm, repoID, currentPath, onNodeClick }) => {
|
||||
}, []);
|
||||
|
||||
const toggleMetadataStatus = useCallback((value) => {
|
||||
if (metadataStatus === value) return;
|
||||
setMetadataStatus(value);
|
||||
}, [metadataStatus]);
|
||||
updateEnableExtendedProperties(value);
|
||||
}, [updateEnableExtendedProperties]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -67,11 +43,11 @@ const DirViews = ({ userPerm, repoID, currentPath, onNodeClick }) => {
|
||||
moreOperations={moreOperations}
|
||||
moreOperationClick={moreOperationClick}
|
||||
>
|
||||
{!loading && metadataStatus && (<MetadataTreeView userPerm={userPerm} repoID={repoID} currentPath={currentPath} onNodeClick={onNodeClick} />)}
|
||||
{enableExtendedProperties && (<MetadataTreeView userPerm={userPerm} repoID={repoID} currentPath={currentPath} onNodeClick={onNodeClick} />)}
|
||||
</TreeSection>
|
||||
{showMetadataStatusManagementDialog && (
|
||||
<MetadataStatusManagementDialog
|
||||
value={metadataStatus}
|
||||
value={enableExtendedProperties}
|
||||
repoID={repoID}
|
||||
toggle={closeMetadataManagementDialog}
|
||||
submit={toggleMetadataStatus}
|
||||
|
@ -6,6 +6,10 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dirent-detail-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.dirent-detail-item .dirent-detail-item-name {
|
||||
width: 160px;
|
||||
padding: 7px 6px;
|
||||
@ -42,10 +46,16 @@
|
||||
}
|
||||
|
||||
.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 .ctime-formatter,
|
||||
.dirent-detail-item .dirent-detail-item-value .mtime-formatter,
|
||||
.dirent-detail-item .dirent-detail-item-value .date-formatter {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.dirent-detail-item .dirent-detail-item-value .date-formatter {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dirent-detail-item-value .creator-formatter {
|
||||
height: 20px;
|
||||
}
|
||||
|
@ -1,21 +1,8 @@
|
||||
@keyframes move {
|
||||
from {
|
||||
right: -500px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
to {
|
||||
right: 0px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.cur-view-detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
width: 400px;
|
||||
height: 100%;
|
||||
border-left: 1px solid #eee;
|
||||
animation: move .5s ease-in-out 1;
|
||||
position: relative;
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ const Detail = ({ children, className }) => {
|
||||
}, [setDragHandlerTop]);
|
||||
|
||||
useEffect(() => {
|
||||
const width = localStorage.getItem('sf_cur_view_detail_width', 300);
|
||||
const lastSettingsValue = localStorage.getItem('sf_cur_view_detail_width');
|
||||
const width = lastSettingsValue ? parseInt(lastSettingsValue) : 300;
|
||||
setWidth(width);
|
||||
}, []);
|
||||
|
||||
|
@ -1,27 +1,19 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { getDirentPath, getFileParent } from './utils';
|
||||
import { getDirentPath } from './utils';
|
||||
import DetailItem from '../detail-item';
|
||||
import { CellType } from '../../../metadata/metadata-view/_basic';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
import { MetadataDetails } from '../../../metadata';
|
||||
import { MetadataDetails, useMetadataStatus } from '../../../metadata';
|
||||
|
||||
const DirDetails = ({ repoID, repoInfo, dirent, path, direntDetail, ...params }) => {
|
||||
const parent = useMemo(() => getFileParent(dirent, path), [dirent, path]);
|
||||
const direntPath = useMemo(() => getDirentPath(dirent, path), [dirent, path]);
|
||||
const { enableExtendedProperties } = useMetadataStatus();
|
||||
|
||||
return (
|
||||
<>
|
||||
<DetailItem field={{ type: CellType.TEXT, name: gettext('Parent folder') }} value={parent} />
|
||||
<DetailItem field={{ type: 'size', name: gettext('Size') }} value={repoInfo.size} />
|
||||
<DetailItem field={{ type: CellType.CREATOR, name: gettext('Creator') }} value={repoInfo.owner_email} collaborators={[{
|
||||
name: repoInfo.owner_name,
|
||||
contact_email: repoInfo.owner_contact_email,
|
||||
email: repoInfo.owner_email,
|
||||
avatar_url: repoInfo.owner_avatar,
|
||||
}]} />
|
||||
<DetailItem field={{ type: CellType.MTIME, name: gettext('Last modified time') }} value={direntDetail.mtime} />
|
||||
{window.app.pageOptions.enableMetadataManagement && (
|
||||
{window.app.pageOptions.enableMetadataManagement && enableExtendedProperties && (
|
||||
<MetadataDetails repoID={repoID} filePath={direntPath} direntType="dir" { ...params } />
|
||||
)}
|
||||
</>
|
||||
|
@ -1,20 +1,20 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
import { getDirentPath, getFileParent } from './utils';
|
||||
import { getDirentPath } from './utils';
|
||||
import DetailItem from '../detail-item';
|
||||
import { CellType } from '../../../metadata/metadata-view/_basic';
|
||||
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 } from '../../../metadata';
|
||||
import { MetadataDetails, useMetadataStatus } 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 [isEditFileTagShow, setEditFileTagShow] = useState(false);
|
||||
const { enableExtendedProperties } = useMetadataStatus();
|
||||
|
||||
const parent = useMemo(() => getFileParent(dirent, path), [dirent, path]);
|
||||
const direntPath = useMemo(() => getDirentPath(dirent, path), [dirent, path]);
|
||||
const tagListTitleID = useMemo(() => `detail-list-view-tags-${uuidV4()}`, []);
|
||||
|
||||
@ -28,7 +28,6 @@ const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail,
|
||||
|
||||
return (
|
||||
<>
|
||||
<DetailItem field={{ type: CellType.TEXT, name: gettext('Parent folder') }} value={parent} />
|
||||
<DetailItem field={{ type: 'size', name: gettext('Size') }} value={Utils.bytesToSize(direntDetail.size)} />
|
||||
<DetailItem field={{ type: CellType.LAST_MODIFIER, name: gettext('Last modifier') }} value={direntDetail.last_modifier_email} collaborators={[{
|
||||
name: direntDetail.last_modifier_name,
|
||||
@ -37,7 +36,7 @@ const FileDetails = React.memo(({ repoID, repoInfo, dirent, path, direntDetail,
|
||||
avatar_url: direntDetail.last_modifier_avatar,
|
||||
}]} />
|
||||
<DetailItem field={{ type: CellType.MTIME, name: gettext('Last modified time') }} value={direntDetail.last_modified} />
|
||||
{!window.app.pageOptions.enableMetadataManagement && (
|
||||
{!window.app.pageOptions.enableMetadataManagement && enableExtendedProperties && (
|
||||
<DetailItem field={{ type: CellType.SINGLE_SELECT, name: gettext('Tags') }} valueId={tagListTitleID} valueClick={onEditFileTagToggle} >
|
||||
{Array.isArray(fileTagList) && fileTagList.length > 0 ? (
|
||||
<FileTagList fileTagList={fileTagList} />
|
||||
|
@ -91,30 +91,34 @@ class DirentDetails extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { dirent, direntDetail, collaborators, collaboratorsCache } = this.state;
|
||||
renderImage = () => {
|
||||
const { dirent } = this.state;
|
||||
if (!dirent) return null;
|
||||
const { repoID, path, fileTags } = this.props;
|
||||
const direntName = dirent.name;
|
||||
const smallIconUrl = Utils.getDirentIcon(dirent);
|
||||
// let bigIconUrl = Utils.getDirentIcon(dirent, true);
|
||||
let bigIconUrl = '';
|
||||
const isImg = Utils.imageCheck(dirent.name);
|
||||
// const isVideo = Utils.videoCheck(dirent.name);
|
||||
if (isImg) {
|
||||
bigIconUrl = `${siteRoot}thumbnail/${repoID}/1024` + Utils.encodePath(`${path === '/' ? '' : path}/${dirent.name}`);
|
||||
}
|
||||
if (!isImg) return null;
|
||||
const { repoID, path } = this.props;
|
||||
const bigIconUrl = `${siteRoot}thumbnail/${repoID}/1024` + Utils.encodePath(`${path === '/' ? '' : path}/${dirent.name}`);
|
||||
return (
|
||||
<div className="detail-image-thumbnail">
|
||||
<img src={bigIconUrl} alt="" className="thumbnail" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { dirent, direntDetail, collaborators, collaboratorsCache } = this.state;
|
||||
const { repoID, path, fileTags } = this.props;
|
||||
const direntName = dirent?.name || '';
|
||||
const smallIconUrl = Utils.getDirentIcon(dirent);
|
||||
|
||||
return (
|
||||
<Detail>
|
||||
<Header title={direntName} icon={smallIconUrl} onClose={this.props.onClose} />
|
||||
<Body>
|
||||
{isImg && (
|
||||
<div className="detail-image-thumbnail">
|
||||
<img src={bigIconUrl} alt="" className="thumbnail" />
|
||||
</div>
|
||||
)}
|
||||
{direntDetail && (
|
||||
{this.renderImage()}
|
||||
{dirent && direntDetail && (
|
||||
<div className="detail-content">
|
||||
{dirent.type !== 'file' ? (
|
||||
<DirDetails
|
||||
|
@ -2,14 +2,16 @@ import { Utils } from '../../../utils/utils';
|
||||
|
||||
export const getDirentPath = (dirent, path) => {
|
||||
if (Utils.isMarkdownFile(path)) return path; // column mode: view file
|
||||
if (dirent.type === 'dir') return path;
|
||||
return Utils.joinPath(path, dirent.name);
|
||||
};
|
||||
|
||||
export const getFileParent = (dirent, path) => {
|
||||
const direntPath = getDirentPath(dirent, path);
|
||||
if (direntPath === '/') return '/';
|
||||
const index = direntPath.lastIndexOf('/');
|
||||
const positionPath = direntPath.slice(0, index);
|
||||
return positionPath || '/';
|
||||
let position = '';
|
||||
if (direntPath !== '/') {
|
||||
const index = direntPath.lastIndexOf('/');
|
||||
const positionPath = direntPath.slice(0, index);
|
||||
position = position + positionPath;
|
||||
}
|
||||
return position;
|
||||
};
|
||||
|
1
frontend/src/metadata/hooks/index.js
Normal file
1
frontend/src/metadata/hooks/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { MetadataStatusProvider, useMetadataStatus } from './metadata-status';
|
50
frontend/src/metadata/hooks/metadata-status.js
Normal file
50
frontend/src/metadata/hooks/metadata-status.js
Normal file
@ -0,0 +1,50 @@
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import metadataAPI from '../api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
|
||||
const MetadataStatusContext = React.createContext(null);
|
||||
|
||||
export const MetadataStatusProvider = ({ repoID, children }) => {
|
||||
const enableMetadataManagement = useMemo(() => {
|
||||
return window.app.pageOptions.enableMetadataManagement;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [window.app.pageOptions.enableMetadataManagement]);
|
||||
|
||||
|
||||
const [enableExtendedProperties, setEnableExtendedProperties] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableMetadataManagement) {
|
||||
setEnableExtendedProperties(false);
|
||||
return;
|
||||
}
|
||||
metadataAPI.getMetadataStatus(repoID).then(res => {
|
||||
setEnableExtendedProperties(res.data.enabled);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(errorMsg);
|
||||
setEnableExtendedProperties(false);
|
||||
});
|
||||
}, [repoID, enableMetadataManagement]);
|
||||
|
||||
const updateEnableExtendedProperties = useCallback((newValue) => {
|
||||
if (newValue === enableExtendedProperties) return;
|
||||
setEnableExtendedProperties(newValue);
|
||||
}, [enableExtendedProperties]);
|
||||
|
||||
return (
|
||||
<MetadataStatusContext.Provider value={{ enableExtendedProperties, updateEnableExtendedProperties }}>
|
||||
{children}
|
||||
</MetadataStatusContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useMetadataStatus = () => {
|
||||
const context = useContext(MetadataStatusContext);
|
||||
if (!context) {
|
||||
throw new Error('\'MetadataStatusContext\' is null');
|
||||
}
|
||||
const { enableExtendedProperties, updateEnableExtendedProperties } = context;
|
||||
return { enableExtendedProperties, updateEnableExtendedProperties };
|
||||
};
|
@ -2,8 +2,12 @@ import SeafileMetadata from './metadata-view';
|
||||
import MetadataStatusManagementDialog from './metadata-status-manage-dialog';
|
||||
import MetadataTreeView from './metadata-tree-view';
|
||||
import MetadataDetails from './metadata-details';
|
||||
import metadataAPI from './api';
|
||||
|
||||
export * from './hooks';
|
||||
|
||||
export {
|
||||
metadataAPI,
|
||||
SeafileMetadata,
|
||||
MetadataStatusManagementDialog,
|
||||
MetadataTreeView,
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import CurDirPath from '../../components/cur-dir-path';
|
||||
import Detail from '../../components/dirent-detail';
|
||||
import DirColumnView from '../../components/dir-view-mode/dir-column-view';
|
||||
import ToolbarForSelectedDirents from '../../components/toolbar/selected-dirents-toolbar';
|
||||
import { MetadataStatusProvider } from '../../metadata/hooks';
|
||||
|
||||
import '../../css/lib-content-view.css';
|
||||
|
||||
@ -120,12 +121,10 @@ class LibContentContainer extends React.Component {
|
||||
|
||||
onPathClick = (path) => {
|
||||
this.props.onMainNavBarClick(path);
|
||||
this.props.closeDirentDetail();
|
||||
};
|
||||
|
||||
onItemClick = (dirent) => {
|
||||
this.props.onItemClick(dirent);
|
||||
this.props.closeDirentDetail();
|
||||
};
|
||||
|
||||
onDirentClick = (dirent, event) => {
|
||||
@ -181,7 +180,7 @@ class LibContentContainer extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<MetadataStatusProvider repoID={repoID}>
|
||||
<div className="cur-view-container">
|
||||
{this.props.currentRepoInfo.status === 'read-only' &&
|
||||
<div className="readonly-tip-message">
|
||||
@ -253,7 +252,6 @@ class LibContentContainer extends React.Component {
|
||||
<div
|
||||
className={`cur-view-content lib-content-container ${this.props.isTreePanelShown ? 'view-mode-container' : ''}`}
|
||||
onScroll={this.onItemsScroll}
|
||||
|
||||
>
|
||||
{!this.props.pathExist && this.errMessage}
|
||||
{this.props.pathExist && (
|
||||
@ -335,7 +333,7 @@ class LibContentContainer extends React.Component {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
</MetadataStatusProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -391,6 +391,7 @@ export const Utils = {
|
||||
},
|
||||
|
||||
getDirentIcon: function (dirent, isBig) {
|
||||
if (!dirent) return mediaUrl + 'img/file/256/' + this.FILEEXT_ICON_MAP['default'];
|
||||
let size = this.isHiDPI() ? 48 : 24;
|
||||
size = isBig ? 192 : size;
|
||||
if (dirent.isDir()) {
|
||||
|
Loading…
Reference in New Issue
Block a user