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

Wiki mode improve (#2539)

This commit is contained in:
Daniel Pan
2018-11-22 11:26:00 +08:00
committed by GitHub
parent 921089bd01
commit fb5d105e6e
24 changed files with 751 additions and 629 deletions

View File

@@ -77,7 +77,7 @@ class CreateFile extends React.Component {
});
} else if (pos === 0 ) {
this.setState({
childName: '(draft)' + this.state.childname,
childName: '(draft)' + this.state.childName,
isDraft: !this.state.isdraft
});
} else {
@@ -93,10 +93,11 @@ class CreateFile extends React.Component {
}
componentDidMount() {
if (this.props.parentPath === '/') {
this.setState({parentPath: this.props.parentPath});
let parentPath = this.props.parentPath;
if (parentPath[parentPath.length - 1] === '/') { // mainPanel
this.setState({parentPath: parentPath});
} else {
this.setState({parentPath: this.props.parentPath + '/'});
this.setState({parentPath: parentPath + '/'}); // sidePanel
}
this.newInput.focus();
this.newInput.setSelectionRange(0,0);

View File

@@ -42,10 +42,11 @@ class CreateForder extends React.Component {
}
componentDidMount() {
if (this.props.parentPath === '/') {
this.setState({parentPath: this.props.parentPath});
let parentPath = this.props.parentPath;
if (parentPath[parentPath.length - 1] === '/') { // mainPanel
this.setState({parentPath: parentPath});
} else {
this.setState({parentPath: this.props.parentPath + '/'});
this.setState({parentPath: parentPath + '/'}); // sidePanel
}
this.newInput.focus();
this.newInput.setSelectionRange(0,0);

View File

@@ -25,7 +25,7 @@ class DetailListView extends React.Component {
getDirentPostion = () => {
let { repo, direntPath } = this.props;
let position = repo.repo_name + '/';
let position = repo.repo_name;
if (direntPath !== '/') {
let index = direntPath.lastIndexOf('/');
let path = direntPath.slice(0, index);
@@ -40,6 +40,10 @@ class DetailListView extends React.Component {
});
}
onFileTagChanged = () => {
this.props.onFileTagChanged(this.props.dirent, this.props.direntPath);
}
render() {
let { direntType, direntDetail, fileTagList } = this.props;
let position = this.getDirentPostion();
@@ -64,7 +68,7 @@ class DetailListView extends React.Component {
<tr><th width="35%"></th><td width="65%"></td></tr>
<tr><th>{gettext('Size')}</th><td>{direntDetail.size}</td></tr>
<tr><th>{gettext('Position')}</th><td>{position}</td></tr>
<tr><th>{gettext('Last Update')}</th><td>{moment(direntDetail.mtime).format('YYYY-MM-DD')}</td></tr>
<tr><th>{gettext('Last Update')}</th><td>{moment(direntDetail.last_modified).fromNow()}</td></tr>
<tr className="file-tag-container"><th>{gettext('Tags')}</th>
<td>
<ul className="file-tag-list">
@@ -88,7 +92,7 @@ class DetailListView extends React.Component {
fileTagList={fileTagList}
filePath={this.props.direntPath}
toggleCancel={this.onEditFileTagToggle}
onFileTagChanged={this.props.onFileTagChanged}
onFileTagChanged={this.onFileTagChanged}
/>
}
</Fragment>

View File

@@ -6,10 +6,9 @@ import URLDecorator from '../../utils/url-decorator';
import Toast from '../toast';
import DirentMenu from './dirent-menu';
import DirentRename from './dirent-rename';
import FileTag from '../../models/file-tag';
const propTypes = {
filePath: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
isItemFreezed: PropTypes.bool.isRequired,
dirent: PropTypes.object.isRequired,
onItemClick: PropTypes.func.isRequired,
@@ -22,7 +21,7 @@ const propTypes = {
onDirentItemMove: PropTypes.func.isRequired,
onDirentItemCopy: PropTypes.func.isRequired,
onItemDetails: PropTypes.func.isRequired,
updateViewList: PropTypes.func.isRequired,
updateDirent: PropTypes.func.isRequired,
currentRepo: PropTypes.object,
isRepoOwner: PropTypes.bool,
};
@@ -36,15 +35,13 @@ class DirentListItem extends React.Component {
highlight: false,
isItemMenuShow: false,
menuPosition: {top: 0, left: 0 },
fileTagList: [],
};
}
componentDidMount() {
document.addEventListener('click', this.onItemMenuHide);
this.getFileTag();
}
componentWillUnmount() {
document.removeEventListener('click', this.onItemMenuHide);
}
@@ -113,21 +110,21 @@ class DirentListItem extends React.Component {
onItemSelected = () => {
//todos;
}
onItemStarred = () => {
let dirent = this.props.dirent;
let filePath = this.getDirentPath(dirent);
if (dirent.starred) {
seafileAPI.unStarFile(repoID, filePath).then(() => {
this.props.updateViewList(this.props.filePath);
this.props.updateDirent(this.props.dirent, "starred", false);
});
} else {
seafileAPI.starFile(repoID, filePath).then(() => {
this.props.updateViewList(this.props.filePath);
this.props.updateDirent(this.props.dirent, "starred", true);
});
}
}
onItemClick = () => {
let direntPath = this.getDirentPath(this.props.dirent);
this.props.onItemClick(direntPath);
@@ -141,13 +138,12 @@ class DirentListItem extends React.Component {
onItemDelete = (e) => {
e.nativeEvent.stopImmediatePropagation(); //for document event
let direntPath = this.getDirentPath(this.props.dirent);
this.props.onItemDelete(direntPath);
this.props.onItemDelete(this.props.dirent);
}
onItemMenuItemClick = (operation) => {
switch(operation) {
case 'Rename':
case 'Rename':
this.onRenameMenuItemClick();
break;
case 'Move':
@@ -202,21 +198,20 @@ class DirentListItem extends React.Component {
this.onRenameCancel();
return false;
}
if (!newName) {
let errMessage = 'It is required.';
Toast.error(gettext(errMessage));
return false;
}
if (newName.indexOf('/') > -1) {
let errMessage = 'Name should not include "/".';
Toast.error(gettext(errMessage));
return false;
}
let direntPath = this.getDirentPath(this.props.dirent);
this.props.onItemRename(direntPath, newName);
this.props.onItemRename(this.props.dirent, newName);
this.onRenameCancel();
}
@@ -226,7 +221,7 @@ class DirentListItem extends React.Component {
});
this.props.onUnfreezedItem();
}
onDirentItemMove = () => {
let direntPath = this.getDirentPath(this.props.dirent);
this.props.onDirentItemMove(this.props.dirent, direntPath);
@@ -252,7 +247,8 @@ class DirentListItem extends React.Component {
onLockItem = () => {
let filePath = this.getDirentPath(this.props.dirent);
seafileAPI.lockfile(repoID, filePath).then(() => {
this.props.updateViewList(this.props.filePath);
this.props.updateDirent(this.props.dirent, "is_locked", true);
this.props.updateDirent(this.props.dirent, "locked_by_me", true);
});
this.onItemMenuHide();
}
@@ -260,14 +256,15 @@ class DirentListItem extends React.Component {
onUnlockItem = () => {
let filePath = this.getDirentPath(this.props.dirent);
seafileAPI.unlockfile(repoID, filePath).then(() => {
this.props.updateViewList(this.props.filePath);
this.props.updateDirent(this.props.dirent, "is_locked", false);
this.props.updateDirent(this.props.dirent, "locked_by_me", false);
});
this.onItemMenuHide();
}
onNewDraft = () => {
let filePath = this.getDirentPath(this.props.dirent);
seafileAPI.createDraft(repoID,filePath).then(res => {
seafileAPI.createDraft(repoID, filePath).then(res => {
let draft_file_Path = res.data.draft_file_path;
let draftId = res.data.id;
let url = URLDecorator.getUrl({type: 'draft_view', repoID: repoID, filePath: draft_file_Path, draftId: draftId});
@@ -303,26 +300,10 @@ class DirentListItem extends React.Component {
}
getDirentPath = (dirent) => {
let path = this.props.filePath;
let path = this.props.path;
return path === '/' ? path + dirent.name : path + '/' + dirent.name;
}
getFileTag = () => {
if (this.props.dirent.type === 'file' && this.props.dirent.file_tags!== undefined) {
let FileTgas = this.props.dirent.file_tags;
let fileTagList = [];
FileTgas.forEach(item => {
let fileTag = new FileTag(item)
fileTagList.push(fileTag)
});
this.setState({fileTagList: fileTagList});
}
}
componentWillReceiveProps() {
this.getFileTag();
}
render() {
let { dirent } = this.props;
return (
@@ -348,7 +329,7 @@ class DirentListItem extends React.Component {
</td>
<td>
<div className="dirent-item tag-list tag-list-stacked ">
{ dirent.type !== 'dir' && this.state.fileTagList.map((fileTag) => {
{ dirent.type !== 'dir' && dirent.file_tags.map((fileTag) => {
return (
<span className={`file-tag bg-${fileTag.color}`} key={fileTag.id} title={fileTag.name}></span>
);
@@ -357,7 +338,7 @@ class DirentListItem extends React.Component {
</td>
<td className="operation">
{
this.state.isOperationShow &&
this.state.isOperationShow &&
<div className="operations">
<ul className="operation-group">
<li className="operation-group-item">
@@ -374,8 +355,8 @@ class DirentListItem extends React.Component {
</li>
</ul>
{
this.state.isItemMenuShow &&
<DirentMenu
this.state.isItemMenuShow &&
<DirentMenu
dirent={this.props.dirent}
menuPosition={this.state.menuPosition}
onMenuItemClick={this.onItemMenuItemClick}

View File

@@ -10,7 +10,7 @@ import MoveDirentDialog from '../dialog/move-dirent-dialog';
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
const propTypes = {
filePath: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
direntList: PropTypes.array.isRequired,
onItemDelete: PropTypes.func.isRequired,
onItemRename: PropTypes.func.isRequired,
@@ -18,7 +18,7 @@ const propTypes = {
onItemMove: PropTypes.func.isRequired,
onItemCopy: PropTypes.func.isRequired,
onItemDetails: PropTypes.func.isRequired,
updateViewList: PropTypes.func.isRequired,
updateDirent: PropTypes.func.isRequired,
isDirentListLoading: PropTypes.bool.isRequired,
isRepoOwner: PropTypes.bool,
currentRepo: PropTypes.object,
@@ -42,7 +42,7 @@ class DirentListView extends React.Component {
onFreezedItem = () => {
this.setState({isItemFreezed: true});
}
onUnfreezedItem = () => {
this.setState({isItemFreezed: false});
}
@@ -70,15 +70,15 @@ class DirentListView extends React.Component {
onItemMove = (repo, direntPath, moveToDirentPath) => {
this.props.onItemMove(repo, direntPath, moveToDirentPath);
}
onCancelMove = () => {
this.setState({isMoveDialogShow: false});
}
onItemCopy = (repo, direntPath, copyToDirentPath) => {
this.props.onItemCopy(repo, direntPath, copyToDirentPath);
}
onCancelCopy = () => {
this.setState({isCopyDialogShow: false});
}
@@ -90,7 +90,7 @@ class DirentListView extends React.Component {
onItemDownload = (dirent, direntPath) => {
if (dirent.type === 'dir') {
this.setState({isProgressDialogShow: true, progress: 0});
editorUtilities.zipDownload(this.props.filePath, dirent.name).then(res => {
editorUtilities.zipDownload(this.props.path, dirent.name).then(res => {
this.zip_token = res.data['zip_token'];
this.addDownloadAnimation();
this.interval = setInterval(this.addDownloadAnimation, 1000);
@@ -161,14 +161,13 @@ class DirentListView extends React.Component {
<DirentListItem
key={index}
dirent={dirent}
filePath={this.props.filePath}
path={this.props.path}
currentRepo={this.props.currentRepo}
isRepoOwner={this.props.isRepoOwner}
onItemClick={this.props.onItemClick}
onRenameMenuItemClick={this.onRenameMenuItemClick}
onItemDelete={this.props.onItemDelete}
onItemRename={this.props.onItemRename}
updateViewList={this.props.updateViewList}
isItemFreezed={this.state.isItemFreezed}
onFreezedItem={this.onFreezedItem}
onUnfreezedItem={this.onUnfreezedItem}
@@ -176,30 +175,31 @@ class DirentListView extends React.Component {
onDirentItemMove={this.onDirentItemMove}
onDirentItemCopy={this.onDirentItemCopy}
onItemDetails={this.onItemDetails}
updateDirent={this.props.updateDirent}
/>
);
})
}
</tbody>
</table>
{this.state.isProgressDialogShow &&
{this.state.isProgressDialogShow &&
<ZipDownloadDialog progress={this.state.progress} onCancelDownload={this.onCancelDownload}
/>
}
{this.state.isMoveDialogShow &&
<MoveDirentDialog
dirent={this.state.currentDirent}
direntPath={this.state.direntPath}
<MoveDirentDialog
dirent={this.state.currentDirent}
direntPath={this.state.direntPath}
onItemMove={this.props.onItemMove}
onCancelMove={this.onCancelMove}
/>
}
{this.state.isCopyDialogShow &&
<CopyDirentDialog
dirent={this.state.currentDirent}
direntPath={this.state.direntPath}
<CopyDirentDialog
dirent={this.state.currentDirent}
direntPath={this.state.direntPath}
onItemCopy={this.props.onItemCopy}
onCancelCopy={this.onCancelCopy}
onCancelCopy={this.onCancelCopy}
/>
}
</Fragment>

View File

@@ -23,7 +23,7 @@ const propTypes = {
minFileSizeErrorCallback: PropTypes.func,
fileTypeErrorCallback: PropTypes.func,
dragAndDrop: PropTypes.bool.isRequired,
filePath: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
onFileSuccess: PropTypes.func.isRequired,
};
@@ -71,7 +71,7 @@ class FileUploader extends React.Component {
bindCallbackHandler = () => {
let {maxFilesErrorCallback, minFileSizeErrorCallback, maxFileSizeErrorCallback, fileTypeErrorCallback } = this.props;
if (maxFilesErrorCallback) {
this.resumable.opts.maxFilesErrorCallback = this.props.maxFilesErrorCallback;
}
@@ -112,7 +112,7 @@ class FileUploader extends React.Component {
return; // is upload a folder;
}
if (enableResumableFileUpload) {
seafileAPI.getFileUploadedBytes(repoID, this.props.filePath, file.fileName).then(res => {
seafileAPI.getFileUploadedBytes(repoID, this.props.path, file.fileName).then(res => {
let uploadedBytes = res.data.uploadedBytes;
let offset = Math.floor(uploadedBytes / (1024 * 1024));
file.markChunksCompleted(offset);
@@ -122,7 +122,7 @@ class FileUploader extends React.Component {
onFileAdded = (resumableFile, files) => {
//get parent_dir、relative_path
let filePath = this.props.filePath === '/' ? '/' : this.props.filePath + '/';
let path = this.props.path === '/' ? '/' : this.props.path + '/';
let fileName = resumableFile.fileName;
let relativePath = resumableFile.relativePath;
let isFile = fileName === relativePath;
@@ -131,12 +131,12 @@ class FileUploader extends React.Component {
resumableFile.formData = {};
if (isFile) {
resumableFile.formData = {
parent_dir: filePath,
parent_dir: path,
};
} else {
let relative_path = relativePath.slice(0, relativePath.lastIndexOf('/') + 1);
resumableFile.formData = {
parent_dir: filePath,
parent_dir: path,
relative_path: relative_path
};
}
@@ -168,7 +168,7 @@ class FileUploader extends React.Component {
}
filesAddedComplete = (resumable, files) => {
// single file uploading can check repetition, because custom dialog conn't prevent program execution;
// single file uploading can check repetition, because custom dialog conn't prevent program execution;
}
setUploadFileList = (files) => {
@@ -198,7 +198,7 @@ class FileUploader extends React.Component {
}
return item;
});
this.setState({uploadFileList: uploadFileList});
}
@@ -216,7 +216,7 @@ class FileUploader extends React.Component {
}
onComplete = () => {
}
onPause = () => [
@@ -238,7 +238,7 @@ class FileUploader extends React.Component {
onCancel = () => {
}
setHeaders = (resumableFile, resumable) => {
let offset = resumable.offset;
let chunkSize = resumable.getOpt('chunkSize');
@@ -249,13 +249,13 @@ class FileUploader extends React.Component {
if (fileSize - resumable.endByte < chunkSize && !resumable.getOpt('forceChunkSize')) {
endByte = fileSize;
}
let headers = {
'Accept': 'application/json; text/javascript, */*; q=0.01',
'Content-Disposition': 'attachment; filename="' + encodeURI(resumableFile.fileName) + '"',
'Content-Range': 'bytes ' + startByte + '-' + endByte + '/' + fileSize,
};
return headers;
}
@@ -277,7 +277,7 @@ class FileUploader extends React.Component {
onFileUpload = () => {
this.uploadInput.removeAttribute('webkitdirectory');
this.uploadInput.click();
seafileAPI.getUploadLink(repoID, this.props.filePath).then(res => {
seafileAPI.getUploadLink(repoID, this.props.path).then(res => {
this.resumable.opts.target = res.data;
});
}
@@ -285,14 +285,14 @@ class FileUploader extends React.Component {
onFolderUpload = () => {
this.uploadInput.setAttribute('webkitdirectory', 'webkitdirectory');
this.uploadInput.click();
seafileAPI.getUploadLink(repoID, this.props.filePath).then(res => {
seafileAPI.getUploadLink(repoID, this.props.path).then(res => {
this.resumable.opts.target = res.data;
});
}
onDragStart = () => {
this.uploadInput.setAttribute('webkitdirectory', 'webkitdirectory');
seafileAPI.getUploadLink(repoID, this.props.filePath).then(res => {
seafileAPI.getUploadLink(repoID, this.props.path).then(res => {
this.resumable.opts.target = res.data;
});
}
@@ -328,13 +328,13 @@ class FileUploader extends React.Component {
// this.setState({isUploadRemindDialogShow: false});
this.setUploadFileList(this.resumable.files);
this.resumable.upload();
}
uploadFile = () => {
// this.setState({isUploadRemindDialogShow: false});
this.setUploadFileList(this.resumable.files);
this.resumable.upload();
}
@@ -352,7 +352,7 @@ class FileUploader extends React.Component {
</div>
{
this.state.isUploadProgressDialogShow &&
<UploadProgressDialog
<UploadProgressDialog
uploadFileList={this.state.uploadFileList}
totalProgress={this.state.totalProgress}
onMinimizeUploadDialog={this.onMinimizeUploadDialog}
@@ -362,7 +362,7 @@ class FileUploader extends React.Component {
}
{
this.state.isUploadRemindDialogShow &&
<UploadRemindDialog
<UploadRemindDialog
currentResumableFile={this.state.currentResumableFile}
replaceRepetitionFile={this.replaceRepetitionFile}
uploadFile={this.uploadFile}

View File

@@ -7,7 +7,7 @@ import CreateTagDialog from '../dialog/create-tag-dialog';
import UpdateTagDialog from '../dialog/update-tag-dialog';
const propTypes = {
filePath: PropTypes.string.isRequired
path: PropTypes.string.isRequired
};
class PathToolbar extends React.Component {
@@ -42,15 +42,13 @@ class PathToolbar extends React.Component {
}
isMarkdownFile(filePath) {
let lastIndex = filePath.lastIndexOf('/');
let name = filePath.slice(lastIndex + 1);
let name = Utils.getFileName(filePath);
return name.indexOf('.md') > -1 ? true : false;
}
render() {
let isFile = this.isMarkdownFile(this.props.filePath);
let index = this.props.filePath.lastIndexOf('/');
let name = this.props.filePath.slice(index + 1);
let isFile = this.isMarkdownFile(this.props.path);
let name = Utils.getFileName(this.props.path);
let trashUrl = siteRoot + 'repo/recycle/' + repoID + '/?referer=' + encodeURIComponent(location.href);
let historyUrl = siteRoot + 'repo/history/' + repoID + '/?referer=' + encodeURIComponent(location.href);
if ( (name === slug || name === '') && !isFile && permission) {
@@ -62,8 +60,8 @@ class PathToolbar extends React.Component {
<li className="toolbar-item"><a className="op-link sf2-icon-history" href={historyUrl} title={gettext('History')} aria-label={gettext('History')}></a></li>
</ul>
{
this.state.isListRepoTagShow &&
<ListTagDialog
this.state.isListRepoTagShow &&
<ListTagDialog
onListTagCancel={this.onListRepoTagToggle}
onCreateRepoTag={this.onCreateRepoTagToggle}
onUpdateRepoTag={this.onUpdateRepoTagToggle}
@@ -71,27 +69,27 @@ class PathToolbar extends React.Component {
}
{
this.state.isCreateRepoTagShow &&
<CreateTagDialog
<CreateTagDialog
toggleCancel={this.onCreateRepoTagToggle}
/>
}
{
this.state.isUpdateRepoTagShow &&
<UpdateTagDialog
currentTag={this.state.currentTag}
<UpdateTagDialog
currentTag={this.state.currentTag}
toggleCancel={this.onUpdateRepoTagToggle}
/>
}
</Fragment>
);
} else if ( !isFile && permission) {
} else if (!isFile && permission) {
return (
<ul className="path-toolbar">
<li className="toolbar-item"><a className="op-link sf2-icon-trash" href={trashUrl} title={gettext('Trash')} aria-label={gettext('Trash')}></a></li>
</ul>
);
} else if (permission) {
historyUrl = siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + Utils.encodePath(this.props.filePath) + '&referer=' + encodeURIComponent(location.href);
historyUrl = siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + Utils.encodePath(this.props.path) + '&referer=' + encodeURIComponent(location.href);
return (
<ul className="path-toolbar">
<li className="toolbar-item"><a className="op-link sf2-icon-history" href={historyUrl} title={gettext('History')} aria-label={gettext('History')}></a></li>

View File

@@ -16,7 +16,7 @@ class Node {
return node;
}
constructor({name, type, size, last_update_time, permission, parent_path, isExpanded, children}) {
this.name = name;
this.type = type;
@@ -28,7 +28,7 @@ class Node {
this.children = children ? children : [];
this.parent = null;
}
clone() {
var n = new Node({
name: this.name,
@@ -39,10 +39,10 @@ class Node {
parent_path: this.parent_path,
isExpanded: this.isExpanded
});
n.children = this.children.map(child => {
var newChild = child.clone();
newChild.parent = n;
return newChild;
n.children = this.children.map(child => {
var newChild = child.clone();
newChild.parent = n;
return newChild;
});
return n;
}
@@ -122,4 +122,4 @@ class Node {
}
export default Node;
export default Node;

View File

@@ -5,7 +5,7 @@ import { permission } from '../../utils/constants';
const propTypes = {
isNodeItemFrezee: PropTypes.bool.isRequired,
currentFilePath: PropTypes.string.isRequired,
currentPath: PropTypes.string.isRequired,
paddingLeft: PropTypes.number.isRequired,
node: PropTypes.object.isRequired,
treeView: PropTypes.object.isRequired,
@@ -31,10 +31,10 @@ class TreeNodeView extends React.Component {
};
}
onClick = (e) => {
onClick = () => {
// e.nativeEvent.stopImmediatePropagation();
let { node } = this.props;
this.props.treeView.onNodeClick(e, node);
this.props.treeView.onNodeClick(node);
}
onMouseEnter = () => {
@@ -55,7 +55,7 @@ class TreeNodeView extends React.Component {
handleCollapse = (e) => {
e.stopPropagation();
this.props.onDirCollapse(e, this.props.node);
this.props.onDirCollapse(this.props.node);
}
onDragStart = (e) => {
@@ -121,7 +121,7 @@ class TreeNodeView extends React.Component {
paddingLeft={this.props.paddingLeft}
treeView={this.props.treeView}
isNodeItemFrezee={this.props.isNodeItemFrezee}
currentFilePath={this.props.currentFilePath}
currentPath={this.props.currentPath}
onDirCollapse={this.props.onDirCollapse}
/>
);
@@ -138,7 +138,7 @@ class TreeNodeView extends React.Component {
let isShow = (this.props.node.path === this.props.currentFilePath);
return (
<div className="right-icon">
<MenuControl
<MenuControl
isShow={this.state.isMenuIconShow || isShow}
onClick={this.onMenuControlClick}
/>
@@ -186,11 +186,11 @@ class TreeNodeView extends React.Component {
return (
<div type={type} className="tree-node" style={styles}>
<div
onMouseLeave={this.onMouseLeave}
<div
onMouseLeave={this.onMouseLeave}
onMouseEnter={this.onMouseEnter}
onClick={this.onClick}
type={type}
type={type}
className={`tree-node-inner text-nowrap ${hlClass} ${node.name === '/'? 'hide': ''}`}
>
<div className="tree-node-text" type={type} draggable="true" onDragStart={this.onDragStart}>{node.name}</div>

View File

@@ -6,7 +6,7 @@ import editorUtilities from '../../utils/editor-utilties';
const propTypes = {
permission: PropTypes.string,
isNodeItemFrezee: PropTypes.bool.isRequired,
currentFilePath: PropTypes.string.isRequired,
currentPath: PropTypes.string.isRequired,
treeData: PropTypes.object.isRequired,
onShowContextMenu: PropTypes.func.isRequired,
onNodeClick: PropTypes.func.isRequired,
@@ -22,18 +22,14 @@ class TreeView extends React.PureComponent {
*/
}
toggleCollapse = (e, node) => {
this.props.onDirCollapse(e, node);
}
onDragStart = (e, node) => {
const url = editorUtilities.getFileURL(node);
e.dataTransfer.setData('text/uri-list', url);
e.dataTransfer.setData('text/plain', url);
}
onNodeClick = (e, node) => {
this.props.onNodeClick(e, node);
onNodeClick = (node) => {
this.props.onNodeClick(node);
}
onShowContextMenu = (e, node) => {
@@ -53,7 +49,7 @@ class TreeView extends React.PureComponent {
node={this.props.treeData.root}
isNodeItemFrezee={this.props.isNodeItemFrezee}
permission={this.props.permission}
currentFilePath={this.props.currentFilePath}
currentPath={this.props.currentPath}
onShowContextMenu={this.props.onShowContextMenu}
onDirCollapse={this.props.onDirCollapse}
/>

View File

@@ -62,6 +62,25 @@ class Tree {
return false;
}
deleteNodeByPath(path) {
let node = this.getNodeByPath(path);
this.deleteNode(node);
}
moveNode(node, moveToNode, isDestroy) {
let moveNode = node.clone();
this.addNodeToParent(moveNode, moveToNode);
if (isDestroy) {
this.deleteNode(node);
}
}
moveNodeByPath(path, moveToPath, isDestroy) {
let node = this.getNodeByPath(path);
let moveToNode = this.getNodeByPath(moveToPath);
this.moveNode(node, moveToNode, isDestroy);
}
updateNodeParam(node, param, newValue) {
let treeNode = this.findNodeFromTree(node);
if (treeNode && treeNode[param]) {
@@ -71,6 +90,11 @@ class Tree {
return false;
}
updateNodeParamByPath(path, param, newValue) {
let node = this.getNodeByPath(path);
this.updateNodeParam(node, param, newValue);
}
findNode(node) {
return this.findNodeFromTree(node);
}