1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-12 21:30:39 +00:00

Add selected menu (#3121)

This commit is contained in:
Michael An
2019-03-18 17:32:49 +08:00
committed by Daniel Pan
parent d3f16e473f
commit 3472f3c5a6
7 changed files with 603 additions and 35 deletions

View File

@@ -10,8 +10,10 @@ require('../../css/repo-tag.css');
const TagItemPropTypes = { const TagItemPropTypes = {
repoID: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired,
repoTag: PropTypes.object.isRequired, repoTag: PropTypes.object.isRequired,
filePath: PropTypes.string.isRequired, filePath: PropTypes.string,
fileTagList: PropTypes.array.isRequired, filesPath: PropTypes.array,
fileTagList: PropTypes.array,
multiFileTagList: PropTypes.array,
onEditFileTag: PropTypes.func.isRequired, onEditFileTag: PropTypes.func.isRequired,
}; };
@@ -20,7 +22,8 @@ class TagItem extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
showSelectedTag: false showSelectedTag: false,
freeze: false,
}; };
} }
@@ -38,25 +41,65 @@ class TagItem extends React.Component {
getRepoTagIdList = () => { getRepoTagIdList = () => {
let repoTagIdList = []; let repoTagIdList = [];
if (this.props.fileTagList.length > 0) {
let fileTagList = this.props.fileTagList; let fileTagList = this.props.fileTagList;
fileTagList.map((fileTag) => { fileTagList.map((fileTag) => {
repoTagIdList.push(fileTag.repo_tag_id); repoTagIdList.push(fileTag.repo_tag_id);
}); });
return repoTagIdList; return repoTagIdList;
} else {
const tagList = this.props.multiFileTagList;
const length = tagList.length;
let tagArray = [];
for (let i = 0; i< length; i++) {
for (let j = 0; j < tagList[i].length; j++) {
tagArray.push(tagList[i][j].repo_tag_id);
}
}
repoTagIdList = this.getCommonTag(tagArray, length);
return repoTagIdList;
}
}
getCommonTag = (filesTags, filesNumber) => {
let hash = {};
let tagNumber = 1;
let commonTags = [];
for (let i = 0, len = filesTags.length; i < len; i++) {
let filesTag = filesTags[i];
if (!hash[filesTag]) {
hash[filesTag] = 1;
} else{
hash[filesTag]++;
}
if (hash[filesTag] == tagNumber) {
if (tagNumber === filesNumber) {
commonTags.push(filesTag);
}
} else if (hash[filesTag] > tagNumber) {
tagNumber = hash[filesTag];
if (tagNumber === filesNumber) {
commonTags.push(filesTag);
}
}
}
return commonTags;
} }
onEditFileTag = () => { onEditFileTag = () => {
let { repoID, repoTag, filePath } = this.props; if (this.state.freeze) return;
let { repoID, repoTag, filePath, filesPath, fileTagList } = this.props;
this.setState({ freeze: true });
if (filesPath.length === 1) {
let repoTagIdList = this.getRepoTagIdList(); let repoTagIdList = this.getRepoTagIdList();
if (repoTagIdList.indexOf(repoTag.id) === -1) { if (repoTagIdList.indexOf(repoTag.id) === -1) {
let id = repoTag.id; seafileAPI.addFileTag(repoID, filePath, repoTag.id).then(() => {
seafileAPI.addFileTag(repoID, filePath, id).then(() => {
repoTagIdList = this.getRepoTagIdList(); repoTagIdList = this.getRepoTagIdList();
this.props.onEditFileTag(); this.props.onEditFileTag();
this.setState({ freeze: false });
}); });
} else { } else {
let fileTag = null; let fileTag = null;
let fileTagList = this.props.fileTagList;
for (let i = 0; i < fileTagList.length; i++) { for (let i = 0; i < fileTagList.length; i++) {
if (fileTagList[i].repo_tag_id === repoTag.id) { if (fileTagList[i].repo_tag_id === repoTag.id) {
fileTag = fileTagList[i]; fileTag = fileTagList[i];
@@ -66,8 +109,36 @@ class TagItem extends React.Component {
seafileAPI.deleteFileTag(repoID, fileTag.id).then(() => { seafileAPI.deleteFileTag(repoID, fileTag.id).then(() => {
repoTagIdList = this.getRepoTagIdList(); repoTagIdList = this.getRepoTagIdList();
this.props.onEditFileTag(); this.props.onEditFileTag();
this.setState({ freeze: false });
}); });
} }
} else {
this.onEditFilesTag();
}
}
onEditFilesTag = () => {
let { repoID, repoTag, filesPath, multiFileTagList } = this.props;
let repoTagIdList = this.getRepoTagIdList();
if (repoTagIdList.indexOf(repoTag.id) === -1) {
for (let i = 0, length = filesPath.length; i < length; i++) {
seafileAPI.addFileTag(repoID, filesPath[i], repoTag.id).then(() => {
this.props.onEditFileTag();
this.setState({ freeze: false });
});
}
} else {
for (let i = 0, len = multiFileTagList.length; i < len; i++) {
for (let j = 0, length = multiFileTagList[i].length; j < length; j++) {
if (multiFileTagList[i][j].repo_tag_id === repoTag.id) {
seafileAPI.deleteFileTag(repoID, multiFileTagList[i][j].file_tag_id).then(() => {
this.props.onEditFileTag();
this.setState({ freeze: false });
});
}
}
}
}
} }
render() { render() {
@@ -93,8 +164,10 @@ TagItem.propTypes = TagItemPropTypes;
const propTypes = { const propTypes = {
repoID: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired,
filePath: PropTypes.string.isRequired, filePath: PropTypes.string,
fileTagList: PropTypes.array.isRequired, filesPath: PropTypes.array,
fileTagList: PropTypes.array,
multiFileTagList: PropTypes.array,
onFileTagChanged: PropTypes.func.isRequired, onFileTagChanged: PropTypes.func.isRequired,
toggleCancel: PropTypes.func.isRequired, toggleCancel: PropTypes.func.isRequired,
}; };
@@ -147,7 +220,9 @@ class EditFileTagDialog extends React.Component {
repoTag={repoTag} repoTag={repoTag}
repoID={this.props.repoID} repoID={this.props.repoID}
filePath={this.props.filePath} filePath={this.props.filePath}
filesPath={this.props.filesPath}
fileTagList={this.props.fileTagList} fileTagList={this.props.fileTagList}
multiFileTagList={this.props.multiFileTagList}
onEditFileTag={this.onEditFileTag} onEditFileTag={this.onEditFileTag}
/> />
); );

View File

@@ -0,0 +1,136 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem, ButtonDropdown } from 'reactstrap';
import { gettext, isPro, enableFileComment, fileAuditEnabled, folderPermEnabled } from '../../utils/constants';
import '../../css/dirents-menu.css';
const propTypes = {
dirents: PropTypes.array.isRequired,
currentRepoInfo: PropTypes.object.isRequired,
isRepoOwner: PropTypes.bool.isRequired,
onMenuItemClick: PropTypes.func.isRequired,
};
class DirentMenu extends React.Component {
constructor(props) {
super(props);
this.state = {
isItemMenuShow: false,
menuList: [],
};
}
calculateMenuList(props) {
const { currentRepoInfo, dirents, isRepoOwner } = props;
const length = dirents.length;
let menuList = [];
if (length === 1) {
if (dirents[0].type === 'dir') {
menuList = ['Share'];
} else if (dirents[0].type === 'file') {
if (dirents[0].is_locked) {
menuList = ['Share', 'Tags', 'Unlock', 'Details', 'Related Files', 'History', 'Open via Client'];
} else {
menuList = ['Share', 'Tags', 'Lock', 'Details', 'Related Files', 'History', 'Open via Client'];
}
if (!(currentRepoInfo.is_admin && currentRepoInfo.permission === 'rw' || isRepoOwner)) {
menuList.splice(2, 1);
}
}
} else if (length > 1) {
menuList = ['Tags'];
for (let i = 0; i < length; i++) {
if (dirents[i].type === 'dir') {
menuList = [];
break;
}
}
}
this.setState({
menuList: menuList,
});
}
translateMenuItem = (menuItem) => {
let translateResult = '';
switch (menuItem) {
case 'Share':
translateResult = gettext('Share');
break;
case 'Tags':
translateResult = gettext('Tags');
break;
case 'Details':
translateResult = gettext('Details');
break;
case 'Lock':
translateResult = gettext('Lock');
break;
case 'Unlock':
translateResult = gettext('Unlock');
break;
case 'Related Files':
translateResult = gettext('Related Files');
break;
case 'History':
translateResult = gettext('History');
break;
case 'Open via Client':
translateResult = gettext('Open via Client');
break;
default:
break;
}
return translateResult;
}
onDropdownToggleClick = (e) => {
e.preventDefault();
this.setState({
isItemMenuShow: !this.state.isItemMenuShow,
});
}
onMenuItemClick = (event) => {
let operation = event.target.dataset.toggle;
this.props.onMenuItemClick(operation, this.props.dirents);
}
componentDidMount() {
this.calculateMenuList(this.props);
}
componentWillReceiveProps(nextProps) {
if (this.props.dirents.length !== nextProps.dirents.length) {
this.calculateMenuList(nextProps);
}
}
render() {
if (this.state.menuList.length === 0) {
return null;
}
return (
<ButtonDropdown isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick} title={gettext('More Operations')}>
<DropdownToggle data-toggle="dropdown" aria-expanded={this.state.isItemMenuShow} onClick={this.onDropdownToggleClick} className="fas fa-ellipsis-v sf-dropdown-toggle dirents-more-menu">
</DropdownToggle>
<DropdownMenu>
{this.state.menuList.map((menuItem, index) => {
if (menuItem === 'Divider') {
return <DropdownItem key={index} divider/>;
} else {
return (
<DropdownItem key={index} data-toggle={menuItem} onClick={this.onMenuItemClick}>{this.translateMenuItem(menuItem)}</DropdownItem>
);
}
})}
</DropdownMenu>
</ButtonDropdown>
);
}
}
DirentMenu.propTypes = propTypes;
export default DirentMenu;

View File

@@ -8,6 +8,13 @@ import URLDecorator from '../../utils/url-decorator';
import ZipDownloadDialog from '../dialog/zip-download-dialog'; import ZipDownloadDialog from '../dialog/zip-download-dialog';
import MoveDirentDialog from '../dialog/move-dirent-dialog'; import MoveDirentDialog from '../dialog/move-dirent-dialog';
import CopyDirentDialog from '../dialog/copy-dirent-dialog'; import CopyDirentDialog from '../dialog/copy-dirent-dialog';
import DirentsMenu from '../dirent-list-view/dirents-menu';
import ShareDialog from '../dialog/share-dialog';
import AddRelatedFileDialog from '../dialog/add-related-file-dialog';
import ListRelatedFileDialog from '../dialog/list-related-file-dialog';
import EditFileTagDialog from '../dialog/edit-filetag-dialog';
import toaster from '../toast';
import ModalPortal from '../modal-portal';
const propTypes = { const propTypes = {
path: PropTypes.string.isRequired, path: PropTypes.string.isRequired,
@@ -17,6 +24,7 @@ const propTypes = {
onItemsMove: PropTypes.func.isRequired, onItemsMove: PropTypes.func.isRequired,
onItemsCopy: PropTypes.func.isRequired, onItemsCopy: PropTypes.func.isRequired,
onItemsDelete: PropTypes.func.isRequired, onItemsDelete: PropTypes.func.isRequired,
isRepoOwner: PropTypes.bool.isRequired,
}; };
class MutipleDirOperationToolbar extends React.Component { class MutipleDirOperationToolbar extends React.Component {
@@ -29,6 +37,13 @@ class MutipleDirOperationToolbar extends React.Component {
isMoveDialogShow: false, isMoveDialogShow: false,
isCopyDialogShow: false, isCopyDialogShow: false,
isMutipleOperation: true, isMutipleOperation: true,
showLibContentViewDialogs: false,
showShareDialog: false,
showEditFileTagDialog: false,
showAddRelatedFileDialog: false,
showListRelatedFileDialog: false,
fileTagList: [],
multiFileTagList: [],
}; };
this.zipToken = null; this.zipToken = null;
} }
@@ -94,15 +109,236 @@ class MutipleDirOperationToolbar extends React.Component {
}); });
} }
onMenuItemClick = (operation) => {
const dirents = this.props.selectedDirentList;
const dirent = dirents[0];
switch(operation) {
case 'Share':
this.setState({
showLibContentViewDialogs: true,
showShareDialog: true,
});
break;
case 'Tags':
this.listFilesTags(dirents);
break;
case 'Details':
this.props.showDirentDetail();
break;
case 'Lock':
this.lockFile(dirent);
break;
case 'Unlock':
this.unlockFile(dirent);
break;
case 'Related Files':
this.openRelatedFilesDialog(dirent);
break;
case 'History':
this.onHistory(dirent);
break;
case 'Open via Client':
this.onOpenViaClient(dirent);
break;
default:
break;
}
}
lockFile = (dirent) => {
const filePath = this.getDirentPath(dirent);
seafileAPI.lockfile(this.props.repoID, filePath).then((res) => {
if (res.data.is_locked) {
let message = gettext('Successfully locked %(name)s.');
message = message.replace('%(name)s', dirent.name);
toaster.success(message);
this.props.updateDirent(dirent, 'is_locked', true);
this.props.updateDirent(dirent, 'locked_by_me', true);
this.props.unSelectDirent();
}
});
}
unlockFile = (dirent) => {
const filePath = this.getDirentPath(dirent);
seafileAPI.unlockfile(this.props.repoID, filePath).then((res) => {
if (!res.data.is_locked) {
let message = gettext('Successfully unlocked %(name)s.');
message = message.replace('%(name)s', dirent.name);
toaster.success(message);
this.props.updateDirent(dirent, 'is_locked', false);
this.props.updateDirent(dirent, 'locked_by_me', false);
this.props.unSelectDirent();
}
});
}
onOpenViaClient = (dirent) => {
const filePath = this.getDirentPath(dirent);
let url = URLDecorator.getUrl({
type: 'open_via_client',
repoID: this.props.repoID,
filePath: filePath
});
location.href = url;
this.props.unSelectDirent();
}
onHistory = (dirent) => {
let filePath = this.getDirentPath(dirent);
let url = URLDecorator.getUrl({
type: 'file_revisions',
repoID: this.props.repoID,
filePath: filePath
});
location.href = url;
}
openRelatedFilesDialog = (dirent) => {
let filePath = this.getDirentPath(dirent);
seafileAPI.listRelatedFiles(this.props.repoID, filePath).then(res => {
this.setState({
relatedFiles: res.data.related_files,
showLibContentViewDialogs: true,
});
if (res.data.related_files.length > 0) {
this.setState({
showListRelatedFileDialog: true,
});
} else {
this.setState({
showAddRelatedFileDialog: true,
});
}
});
}
toggleCancel = () => {
this.setState({
showLibContentViewDialogs: false,
showShareDialog: false,
showEditFileTagDialog: false,
showAddRelatedFileDialog: false,
showListRelatedFileDialog: false,
});
}
closeAddRelatedFileDialog = () => {
this.setState({
showLibContentViewDialogs: true,
showAddRelatedFileDialog: false,
showListRelatedFileDialog: true,
});
}
addRelatedFileToggle = () => {
this.setState({
showLibContentViewDialogs: true,
showAddRelatedFileDialog: true,
showListRelatedFileDialog: false,
});
}
listFilesTags = (dirents) => {
if (dirents.length === 1) {
this.listFileTags(dirents[0]);
} else if (dirents.length > 1) {
this.listMultiFileTags(dirents);
}
this.setState({
showLibContentViewDialogs: true,
showEditFileTagDialog: true,
});
}
listFileTags = (dirent) => {
let filePath = this.getDirentPath(dirent);
seafileAPI.listFileTags(this.props.repoID, filePath).then(res => {
let fileTagList = res.data.file_tags;
for (let i = 0, length = fileTagList.length; i < length; i++) {
fileTagList[i].id = fileTagList[i].file_tag_id;
}
this.setState({
fileTagList: fileTagList
});
});
}
listMultiFileTags = (dirents) => {
let multiFileTagList = [];
let len = dirents.length;
for (let j = 0; j < len; j++) {
seafileAPI.listFileTags(this.props.repoID, this.getDirentPath(dirents[j])).then(res => {
let fileTagList = res.data.file_tags;
for (let i = 0, length = fileTagList.length; i < length; i++) {
fileTagList[i].id = fileTagList[i].file_tag_id;
}
multiFileTagList.push(fileTagList);
});
this.setState({
multiFileTagList: multiFileTagList
});
}
}
onMenuFileTagChanged = () => {
this.listMultiFileTags(this.props.selectedDirentList);
this.listFileTags(this.props.selectedDirentList[0]);
let length = this.props.selectedDirentList.length;
for (let i = 0; i < length; i++) {
const dirent = this.props.selectedDirentList[i];
const direntPath = this.getDirentPath(dirent);
this.props.onFilesTagChanged(dirent, direntPath);
}
}
listRelatedFiles = (dirent) => {
let filePath = this.getDirentPath(dirent);
seafileAPI.listRelatedFiles(this.props.repoID, filePath).then(res => {
this.setState({
relatedFiles: res.data.related_files
});
});
}
onRelatedFileChange = () => {
this.listRelatedFiles(this.props.selectedDirentList[0]);
}
getDirentPath = (dirent) => {
if (dirent) return Utils.joinPath(this.state.path, dirent.name);
}
render() { render() {
const { repoID } = this.props;
let direntPath = this.getDirentPath(this.props.selectedDirentList[0]);
let direntsPath = [];
if (this.state.showLibContentViewDialogs && this.props.selectedDirentList.length > 0) {
for (let i = 0; i < this.props.selectedDirentList.length; i++) {
let newDirentPath = this.getDirentPath(this.props.selectedDirentList[i]);
direntsPath.push(newDirentPath);
}
}
return ( return (
<Fragment> <Fragment>
<div className="d-flex">
<ButtonGroup className="flex-row group-operations"> <ButtonGroup className="flex-row group-operations">
<Button className="secondary group-op-item action-icon sf2-icon-move" title={gettext('Move')} onClick={this.onMoveToggle}></Button> <Button className="secondary group-op-item action-icon sf2-icon-move" title={gettext('Move')} onClick={this.onMoveToggle}></Button>
<Button className="secondary group-op-item action-icon sf2-icon-copy" title={gettext('Copy')} onClick={this.onCopyToggle}></Button> <Button className="secondary group-op-item action-icon sf2-icon-copy" title={gettext('Copy')} onClick={this.onCopyToggle}></Button>
<Button className="secondary group-op-item action-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemsDelete}></Button> <Button className="secondary group-op-item action-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemsDelete}></Button>
<Button className="secondary group-op-item action-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemsDownload}></Button> <Button className="secondary group-op-item action-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemsDownload}></Button>
</ButtonGroup> </ButtonGroup>
{
this.props.selectedDirentList.length > 0 &&
<DirentsMenu
dirents={this.props.selectedDirentList}
currentRepoInfo={this.props.currentRepoInfo}
isRepoOwner={this.props.isRepoOwner}
onMenuItemClick={this.onMenuItemClick}
/>
}
</div>
{this.state.isMoveDialogShow && {this.state.isMoveDialogShow &&
<MoveDirentDialog <MoveDirentDialog
path={this.props.path} path={this.props.path}
@@ -128,6 +364,62 @@ class MutipleDirOperationToolbar extends React.Component {
{this.state.isProgressDialogShow && {this.state.isProgressDialogShow &&
<ZipDownloadDialog progress={this.state.progress} onCancelDownload={this.onCancelDownload} /> <ZipDownloadDialog progress={this.state.progress} onCancelDownload={this.onCancelDownload} />
} }
{this.state.showLibContentViewDialogs && (
<Fragment>
{this.state.showShareDialog &&
<ModalPortal>
<ShareDialog
itemType={this.props.selectedDirentList[0].type}
itemName={this.props.selectedDirentList[0].name}
itemPath={direntPath}
userPerm={this.props.selectedDirentList[0].permission}
repoID={repoID}
repoEncrypted={false}
enableDirPrivateShare={this.props.enableDirPrivateShare}
isGroupOwnedRepo={this.state.isGroupOwnedRepo}
toggleDialog={this.toggleCancel}
/>
</ModalPortal>
}
{this.state.showEditFileTagDialog &&
<ModalPortal>
<EditFileTagDialog
repoID={repoID}
filePath={direntPath}
filesPath={direntsPath}
fileTagList={this.state.fileTagList}
multiFileTagList={this.state.multiFileTagList}
toggleCancel={this.toggleCancel}
onFileTagChanged={this.onMenuFileTagChanged}
selectedDirentList={this.props.selectedDirentList}
/>
</ModalPortal>
}
{this.state.showListRelatedFileDialog &&
<ModalPortal>
<ListRelatedFileDialog
repoID={repoID}
filePath={direntPath}
relatedFiles={this.state.relatedFiles}
toggleCancel={this.toggleCancel}
addRelatedFileToggle={this.addRelatedFileToggle}
onRelatedFileChange={this.onRelatedFileChange}
/>
</ModalPortal>
}
{this.state.showAddRelatedFileDialog &&
<ModalPortal>
<AddRelatedFileDialog
repoID={repoID}
filePath={direntPath}
toggleCancel={this.closeAddRelatedFileDialog}
dirent={this.props.selectedDirentList[0]}
onRelatedFileChange={this.onRelatedFileChange}
/>
</ModalPortal>
}
</Fragment>
)}
</Fragment> </Fragment>
); );
} }

View File

@@ -0,0 +1,10 @@
.dirents-more-menu {
margin-right: 10px;
margin-left: -9px;
padding: 4px 15px;
border: 1px solid #ccc;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}

View File

@@ -113,6 +113,15 @@ class LibContentContainer extends React.Component {
this.setState({isDirentDetailShow: false}); this.setState({isDirentDetailShow: false});
} }
componentWillReceiveProps (nextProps) {
if (nextProps.isDirentDetailShow !== this.state.isDirentDetailShow) {
this.setState({
isDirentDetailShow: nextProps.isDirentDetailShow,
currentDirent: nextProps.selectedDirent,
});
}
}
render() { render() {
let { path, repoID, usedRepoTags, readmeMarkdown, draftCounts } = this.props; let { path, repoID, usedRepoTags, readmeMarkdown, draftCounts } = this.props;
let isRepoInfoBarShow = false; let isRepoInfoBarShow = false;

View File

@@ -43,6 +43,13 @@ const propTypes = {
switchViewMode: PropTypes.func.isRequired, switchViewMode: PropTypes.func.isRequired,
// search // search
onSearchedClick: PropTypes.func.isRequired, onSearchedClick: PropTypes.func.isRequired,
isRepoOwner: PropTypes.bool.isRequired,
// selected menu
onDirentSelected: PropTypes.func.isRequired,
showDirentDetail: PropTypes.func.isRequired,
listRelatedFiles: PropTypes.func.isRequired,
onFilesTagChanged: PropTypes.func.isRequired,
updateDirent: PropTypes.func.isRequired,
}; };
class LibContentToolbar extends React.Component { class LibContentToolbar extends React.Component {
@@ -65,7 +72,7 @@ class LibContentToolbar extends React.Component {
hasDraft={this.props.hasDraft} hasDraft={this.props.hasDraft}
fileTags={this.props.fileTags} fileTags={this.props.fileTags}
relatedFiles={this.props.relatedFiles} relatedFiles={this.props.relatedFiles}
onFileTagChanged={this.props.onFileTagChanged} onFilesTagChanged={this.props.onFilesTagChanged}
onRelatedFileChange={this.props.onRelatedFileChange} onRelatedFileChange={this.props.onRelatedFileChange}
/> />
<ViewModeToolbar currentMode={this.props.currentMode} switchViewMode={this.props.switchViewMode}/> <ViewModeToolbar currentMode={this.props.currentMode} switchViewMode={this.props.switchViewMode}/>
@@ -89,6 +96,17 @@ class LibContentToolbar extends React.Component {
onItemsMove={this.props.onItemsMove} onItemsMove={this.props.onItemsMove}
onItemsCopy={this.props.onItemsCopy} onItemsCopy={this.props.onItemsCopy}
onItemsDelete={this.props.onItemsDelete} onItemsDelete={this.props.onItemsDelete}
isRepoOwner={this.props.isRepoOwner}
currentRepoInfo={this.props.currentRepoInfo}
enableDirPrivateShare={this.props.enableDirPrivateShare}
onFileTagChanged={this.props.onFileTagChanged}
updateDirent={this.props.updateDirent}
onDirentSelected={this.props.onDirentSelected}
showDirentDetail={this.props.showDirentDetail}
listRelatedFiles={this.props.listRelatedFiles}
relatedFiles={this.props.relatedFiles}
unSelectDirent={this.props.unSelectDirent}
onFilesTagChanged={this.props.onFilesTagChanged}
/> : /> :
<DirOperationToolBar <DirOperationToolBar
path={this.props.path} path={this.props.path}

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import cookie from 'react-cookies'; import cookie from 'react-cookies';
import moment from 'moment'; import moment from 'moment';
@@ -69,6 +69,7 @@ class LibContentView extends React.Component {
isAllDirentSelected: false, isAllDirentSelected: false,
dirID: '', // for update dir list dirID: '', // for update dir list
errorMsg: '', errorMsg: '',
isDirentDetailShow: false,
}; };
window.onpopstate = this.onpopstate; window.onpopstate = this.onpopstate;
@@ -76,6 +77,12 @@ class LibContentView extends React.Component {
this.isNeedUpdateHistoryState = true; // Load, refresh page, switch mode for the first time, no need to set historyState this.isNeedUpdateHistoryState = true; // Load, refresh page, switch mode for the first time, no need to set historyState
} }
showDirentDetail = () => {
this.setState({
isDirentDetailShow: true,
});
}
componentWillMount() { componentWillMount() {
const hash = window.location.hash; const hash = window.location.hash;
if (hash.slice(0, 1) === '#') { if (hash.slice(0, 1) === '#') {
@@ -1202,7 +1209,17 @@ class LibContentView extends React.Component {
}); });
} }
unSelectDirent = () => {
this.setState({
isDirentSelected: false,
selectedDirentList: []
});
const dirent = {};
this.onDirentSelected(dirent);
}
render() { render() {
const { repoID } = this.props;
if (this.state.libNeedDecrypt) { if (this.state.libNeedDecrypt) {
return ( return (
@@ -1246,6 +1263,7 @@ class LibContentView extends React.Component {
} }
return ( return (
<div className="main-panel o-hidden"> <div className="main-panel o-hidden">
<div className="main-panel-north border-left-show"> <div className="main-panel-north border-left-show">
@@ -1280,6 +1298,14 @@ class LibContentView extends React.Component {
currentMode={this.state.currentMode} currentMode={this.state.currentMode}
switchViewMode={this.switchViewMode} switchViewMode={this.switchViewMode}
onSearchedClick={this.onSearchedClick} onSearchedClick={this.onSearchedClick}
isRepoOwner={isRepoOwner}
currentRepoInfo={this.state.currentRepoInfo}
updateDirent={this.updateDirent}
onDirentSelected={this.onDirentSelected}
showDirentDetail={this.showDirentDetail}
listRelatedFiles={this.listRelatedFiles}
unSelectDirent={this.unSelectDirent}
onFilesTagChanged={this.onFileTagChanged}
/> />
</div> </div>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
@@ -1342,6 +1368,8 @@ class LibContentView extends React.Component {
isDirentSelected={this.state.isDirentSelected} isDirentSelected={this.state.isDirentSelected}
isAllDirentSelected={this.state.isAllDirentSelected} isAllDirentSelected={this.state.isAllDirentSelected}
onAllDirentSelected={this.onAllDirentSelected} onAllDirentSelected={this.onAllDirentSelected}
isDirentDetailShow={this.state.isDirentDetailShow}
selectedDirent={this.state.selectedDirentList && this.state.selectedDirentList[0]}
/> />
{this.state.pathExist && !this.state.isViewFile && ( {this.state.pathExist && !this.state.isViewFile && (
<FileUploader <FileUploader