mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-09 10:57:27 +00:00
Rename component improve (#2912)
* optimized rename component * optimized rename component
This commit is contained in:
parent
ee82950439
commit
aa32895f1d
@ -6,9 +6,8 @@ import { gettext, siteRoot, mediaUrl, canGenerateShareLink, canGenerateUploadLin
|
|||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import URLDecorator from '../../utils/url-decorator';
|
import URLDecorator from '../../utils/url-decorator';
|
||||||
import toaster from '../toast';
|
|
||||||
import DirentMenu from './dirent-menu';
|
import DirentMenu from './dirent-menu';
|
||||||
import DirentRename from './dirent-rename';
|
import Rename from '../rename';
|
||||||
import ModalPortal from '../modal-portal';
|
import ModalPortal from '../modal-portal';
|
||||||
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';
|
||||||
@ -194,23 +193,6 @@ class DirentListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRenameConfirm = (newName) => {
|
onRenameConfirm = (newName) => {
|
||||||
if (newName === this.props.dirent.name) {
|
|
||||||
this.onRenameCancel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newName) {
|
|
||||||
let errMessage = gettext('Name is required.');
|
|
||||||
toaster.danger(errMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newName.indexOf('/') > -1) {
|
|
||||||
let errMessage = gettext('Name should not include ' + '\'/\'' + '.');
|
|
||||||
toaster.danger(errMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onItemRename(this.props.dirent, newName);
|
this.props.onItemRename(this.props.dirent, newName);
|
||||||
this.onRenameCancel();
|
this.onRenameCancel();
|
||||||
}
|
}
|
||||||
@ -384,7 +366,7 @@ class DirentListItem extends React.Component {
|
|||||||
</td>
|
</td>
|
||||||
<td className="name">
|
<td className="name">
|
||||||
{this.state.isRenameing ?
|
{this.state.isRenameing ?
|
||||||
<DirentRename dirent={dirent} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/> :
|
<Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> :
|
||||||
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
|
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
dirent: PropTypes.object.isRequired,
|
|
||||||
onRenameConfirm: PropTypes.func.isRequired,
|
|
||||||
onRenameCancel: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
class DirentRename extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
name: props.dirent.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.refs.renameInput.focus();
|
|
||||||
if (this.props.dirent.type === 'file') {
|
|
||||||
var endIndex = this.props.dirent.name.lastIndexOf('.');
|
|
||||||
this.refs.renameInput.setSelectionRange(0, endIndex, 'forward');
|
|
||||||
} else {
|
|
||||||
this.refs.renameInput.setSelectionRange(0, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = (e) => {
|
|
||||||
this.setState({name: e.target.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick = (e) => {
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeyPress = (e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
this.onRenameConfirm(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onRenameConfirm = (e) => {
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
this.props.onRenameConfirm(this.state.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRenameCancel = (e) => {
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
this.props.onRenameCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="rename-container">
|
|
||||||
<input
|
|
||||||
ref="renameInput"
|
|
||||||
value={this.state.name}
|
|
||||||
onChange={this.onChange}
|
|
||||||
onKeyPress={this.onKeyPress}
|
|
||||||
onClick={this.onClick}
|
|
||||||
/>
|
|
||||||
<button className="btn btn-secondary sf2-icon-confirm confirm" onClick={this.onRenameConfirm}></button>
|
|
||||||
<button className="btn btn-secondary sf2-icon-cancel cancel" onClick={this.onRenameCancel}></button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DirentRename.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default DirentRename;
|
|
@ -1,13 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { gettext } from '../utils/constants'
|
||||||
|
import toaster from './toast';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
type: PropTypes.string,
|
hasSuffix: PropTypes.bool,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
onRenameConfirm: PropTypes.func.isRequired,
|
onRenameConfirm: PropTypes.func.isRequired,
|
||||||
onRenameCancel: PropTypes.func.isRequired,
|
onRenameCancel: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
class RenameInput extends React.Component {
|
|
||||||
|
class Rename extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -18,7 +21,7 @@ class RenameInput extends React.Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.refs.renameInput.focus();
|
this.refs.renameInput.focus();
|
||||||
if (this.props.type === 'file') {
|
if (this.props.hasSuffix) {
|
||||||
var endIndex = this.props.name.lastIndexOf('.');
|
var endIndex = this.props.name.lastIndexOf('.');
|
||||||
this.refs.renameInput.setSelectionRange(0, endIndex, 'forward');
|
this.refs.renameInput.setSelectionRange(0, endIndex, 'forward');
|
||||||
} else {
|
} else {
|
||||||
@ -42,7 +45,18 @@ class RenameInput extends React.Component {
|
|||||||
|
|
||||||
onRenameConfirm = (e) => {
|
onRenameConfirm = (e) => {
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
this.props.onRenameConfirm(this.state.name);
|
let newName = this.state.name.trim();
|
||||||
|
if (newName === this.props.name) {
|
||||||
|
this.props.onRenameCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { isValid, errMessage } = this.validateInput();
|
||||||
|
if (!isValid) {
|
||||||
|
toaster.danger(errMessage);
|
||||||
|
} else {
|
||||||
|
this.props.onRenameConfirm(newName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onRenameCancel = (e) => {
|
onRenameCancel = (e) => {
|
||||||
@ -50,6 +64,25 @@ class RenameInput extends React.Component {
|
|||||||
this.props.onRenameCancel();
|
this.props.onRenameCancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateInput = () => {
|
||||||
|
let newName = this.state.name.trim();
|
||||||
|
let isValid = true;
|
||||||
|
let errMessage = '';
|
||||||
|
if (!newName) {
|
||||||
|
isValid = false;
|
||||||
|
errMessage = gettext('Name is required.');
|
||||||
|
return { isValid, errMessage };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newName.indexOf('/') > -1) {
|
||||||
|
isValid = false;
|
||||||
|
errMessage = gettext('Name should not include ' + '\'/\'' + '.');
|
||||||
|
return { isValid, errMessage };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isValid, errMessage };
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="rename-container">
|
<div className="rename-container">
|
||||||
@ -67,6 +100,6 @@ class RenameInput extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RenameInput.propTypes = propTypes;
|
Rename.propTypes = propTypes;
|
||||||
|
|
||||||
export default RenameInput;
|
export default Rename;
|
@ -8,7 +8,7 @@ import WikiPermissionEditor from '../select-editor/wiki-permission-editor.js';
|
|||||||
import Toast from '../toast';
|
import Toast from '../toast';
|
||||||
import ModalPortal from '../modal-portal';
|
import ModalPortal from '../modal-portal';
|
||||||
import WikiDeleteDialog from '../dialog/wiki-delete-dialog';
|
import WikiDeleteDialog from '../dialog/wiki-delete-dialog';
|
||||||
import WikiRename from './wiki-rename';
|
import Rename from '../rename';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
wiki: PropTypes.object.isRequired,
|
wiki: PropTypes.object.isRequired,
|
||||||
@ -100,22 +100,6 @@ class WikiListItem extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRenameConfirm = (newName) => {
|
onRenameConfirm = (newName) => {
|
||||||
let wiki = this.props.wiki;
|
|
||||||
|
|
||||||
if (newName === wiki.name) {
|
|
||||||
this.onRenameCancel();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!newName) {
|
|
||||||
let errMessage = gettext('Name is required.');
|
|
||||||
Toast.error(errMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (newName.indexOf('/') > -1) {
|
|
||||||
let errMessage = gettext('Name should not include ' + '\'/\'' + '.');
|
|
||||||
Toast.error(errMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.renameWiki(newName);
|
this.renameWiki(newName);
|
||||||
this.onRenameCancel();
|
this.onRenameCancel();
|
||||||
}
|
}
|
||||||
@ -163,7 +147,7 @@ class WikiListItem extends Component {
|
|||||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||||
<td className="name">
|
<td className="name">
|
||||||
{this.state.isRenameing ?
|
{this.state.isRenameing ?
|
||||||
<WikiRename wiki={wiki} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/> :
|
<Rename wiki={wiki} name={wiki.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/> :
|
||||||
<a href={wiki.link}>{wiki.name}</a>
|
<a href={wiki.link}>{wiki.name}</a>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
wiki: PropTypes.object.isRequired,
|
|
||||||
onRenameConfirm: PropTypes.func.isRequired,
|
|
||||||
onRenameCancel: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
class WikiRename extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
name: props.wiki.name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.refs.renameInput.focus();
|
|
||||||
this.refs.renameInput.setSelectionRange(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = (e) => {
|
|
||||||
this.setState({name: e.target.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeyPress = (e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
this.onRenameConfirm(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onRenameConfirm = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
this.props.onRenameConfirm(this.state.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRenameCancel = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
|
||||||
this.props.onRenameCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="rename-container">
|
|
||||||
<input
|
|
||||||
ref="renameInput"
|
|
||||||
value={this.state.name}
|
|
||||||
onChange={this.onChange}
|
|
||||||
onKeyPress={this.onKeyPress}
|
|
||||||
onClick={this.onClick}
|
|
||||||
/>
|
|
||||||
<button className="btn btn-secondary sf2-icon-confirm confirm" onClick={this.onRenameConfirm}></button>
|
|
||||||
<button className="btn btn-secondary sf2-icon-cancel cancel" onClick={this.onRenameCancel}></button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WikiRename.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default WikiRename;
|
|
@ -6,7 +6,7 @@ import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap
|
|||||||
import { gettext, siteRoot, storages, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants';
|
import { gettext, siteRoot, storages, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import RenameInput from '../../components/rename-input';
|
import Rename from '../../components/rename';
|
||||||
import ModalPotal from '../../components/modal-portal';
|
import ModalPotal from '../../components/modal-portal';
|
||||||
import ShareDialog from '../../components/dialog/share-dialog';
|
import ShareDialog from '../../components/dialog/share-dialog';
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ class Item extends Component {
|
|||||||
<td><img src={data.icon_url} title={data.icon_title} alt={data.icon_title} width="24" /></td>
|
<td><img src={data.icon_url} title={data.icon_title} alt={data.icon_title} width="24" /></td>
|
||||||
<td>
|
<td>
|
||||||
{this.state.showChangeLibName && (
|
{this.state.showChangeLibName && (
|
||||||
<RenameInput
|
<Rename
|
||||||
name={data.repo_name}
|
name={data.repo_name}
|
||||||
onRenameConfirm={this.onRenameConfirm}
|
onRenameConfirm={this.onRenameConfirm}
|
||||||
onRenameCancel={this.onRenameCancel}
|
onRenameCancel={this.onRenameCancel}
|
||||||
|
Loading…
Reference in New Issue
Block a user