1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-13 05:39:59 +00:00

modify code structure

This commit is contained in:
shanshuirenjia
2018-12-11 08:42:30 +08:00
parent f74d9b983c
commit 197995e34a
7 changed files with 248 additions and 236 deletions

View File

@@ -0,0 +1,186 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { gettext, siteRoot } from '../../utils/constants';
import ModalPortal from '../modal-portal';
import WikiDeleteDialog from '../dialog/wiki-delete-dialog';
import MenuControl from '../menu-control';
import Toast from '../toast';
import WikiMenu from './wiki-menu';
import WikiRename from './wiki-rename';
const itempropTypes = {
wiki: PropTypes.object.isRequired,
renameWiki: PropTypes.func.isRequired,
deleteWiki: PropTypes.func.isRequired,
};
class WikiListItem extends Component {
constructor(props) {
super(props);
this.state = {
isShowWikiMenu: false,
position: {top:'', left: ''},
isItemFreezed: false,
isShowDeleteDialog: false,
isShowMenuControl: false,
isRenameing: false,
highlight: '',
};
}
componentDidMount() {
document.addEventListener('click', this.onHideWikiMenu);
}
componentWillUnmount() {
document.removeEventListener('click', this.onHideWikiMenu);
}
onMenuToggle = (e) => {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
if (this.state.isShowWikiMenu) {
this.onHideWikiMenu();
} else {
this.onShowWikiMenu(e);
}
}
onShowWikiMenu = (e) => {
let left = e.clientX - 8*16;
let top = e.clientY + 12;
let position = {top: top, left: left};
this.setState({
isShowWikiMenu: true,
position: position,
isItemFreezed: true,
});
}
onHideWikiMenu = () => {
this.setState({
isShowWikiMenu: false,
isItemFreezed: false,
});
}
onMouseEnter = () => {
if (!this.state.isItemFreezed) {
this.setState({
isShowMenuControl: true,
highlight: 'tr-highlight',
});
}
}
onMouseLeave = () => {
if (!this.state.isItemFreezed) {
this.setState({
isShowMenuControl: false,
highlight: '',
});
}
}
onRenameToggle = () => {
this.setState({
isShowWikiMenu: false,
isItemFreezed: true,
isRenameing: true,
});
}
onRenameConfirm = (newName) => {
let wiki = this.props.wiki;
if (newName === wiki.name) {
this.onRenameCancel();
return false;
}
if (!newName) {
let errMessage = 'Name is required.';
Toast.error(gettext(errMessage));
return false;
}
if (newName.indexOf('/') > -1) {
let errMessage = 'Name should not include ' + '\'/\'' + '.';
Toast.error(gettext(errMessage));
return false;
}
this.renameWiki(newName);
this.onRenameCancel();
}
onRenameCancel = () => {
this.setState({
isRenameing: false,
isItemFreezed: false,
});
}
onDeleteToggle = () => {
this.setState({
isShowDeleteDialog: !this.state.isShowDeleteDialog,
});
}
renameWiki = (newName) => {
let wiki = this.props.wiki;
this.props.renameWiki(wiki, newName);
}
deleteWiki = () => {
let wiki = this.props.wiki;
this.props.deleteWiki(wiki);
this.setState({
isShowDeleteDialog: !this.state.isShowDeleteDialog,
});
}
render() {
let wiki = this.props.wiki;
let userProfileURL = `${siteRoot}profile/${encodeURIComponent(wiki.owner)}/`;
return (
<Fragment>
<tr className={this.state.highlight} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td>
{this.state.isRenameing ?
<WikiRename wiki={wiki} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/> :
<a href={wiki.link}>{gettext(wiki.name)}</a>
}
</td>
<td><a href={userProfileURL} target='_blank'>{gettext(wiki.owner_nickname)}</a></td>
<td>{moment(wiki.updated_at).fromNow()}</td>
<td className="menu-toggle" onClick={this.onMenuToggle}>
<MenuControl
isShow={this.state.isShowMenuControl}
onClick={this.onMenuToggle}
/>
{this.state.isShowWikiMenu &&
<WikiMenu
position={this.state.position}
onRenameToggle={this.onRenameToggle}
onDeleteToggle={this.onDeleteToggle}
/>
}
</td>
</tr>
{this.state.isShowDeleteDialog &&
<ModalPortal>
<WikiDeleteDialog
toggleCancel={this.onDeleteToggle}
handleSubmit={this.deleteWiki}
/>
</ModalPortal>
}
</Fragment>
);
}
}
WikiListItem.propTypes = itempropTypes;
export default WikiListItem;

View File

@@ -0,0 +1,49 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants';
import WikiListItem from './wiki-list-item';
const contentpropTypes = {
data: PropTypes.object.isRequired,
renameWiki: PropTypes.func.isRequired,
deleteWiki: PropTypes.func.isRequired,
};
class WikiListView extends Component {
render() {
let {loading, errorMsg, wikis} = this.props.data;
if (loading) {
return <span className="loading-icon loading-tip"></span>;
} else if (errorMsg) {
return <p className="error text-center">{errorMsg}</p>;
} else {
return (
<table>
<thead>
<tr>
<th width="50%">{gettext('Name')}</th>
<th width="20%">{gettext('Owner')}</th>
<th width="20%">{gettext('Last Update')}</th>
<th width="10%">{/* operation */}</th>
</tr>
</thead>
<tbody>
{wikis.map((wiki, index) => {
return(
<WikiListItem key={index} wiki={wiki}
renameWiki={this.props.renameWiki}
deleteWiki={this.props.deleteWiki}
/>);
})}
</tbody>
</table>
);
}
}
}
WikiListView.propTypes = contentpropTypes;
export default WikiListView;

View File

@@ -0,0 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants';
const propTypes = {
position: PropTypes.object.isRequired,
onRenameToggle: PropTypes.func.isRequired,
onDeleteToggle: PropTypes.func.isRequired,
};
class WikiMenu extends React.Component {
render() {
let position = this.props.position;
let style = {position: 'fixed', top: position.top, left: position.left, display: 'block'};
return (
<ul className="dropdown-menu" style={style}>
<li className="dropdown-item" onClick={this.props.onRenameToggle}>{gettext('Rename')}</li>
<li className="dropdown-item" onClick={this.props.onDeleteToggle}>{gettext('Delete')}</li>
</ul>
);
}
}
WikiMenu.propTypes = propTypes;
export default WikiMenu;

View File

@@ -0,0 +1,69 @@
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;