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

Draft menu improve (#2981)

* [update]draft menu implement method

* update menu style

* repair word error
This commit is contained in:
杨顺强
2019-02-22 11:10:33 +08:00
committed by Daniel Pan
parent 334c87e11a
commit 911b5cbdb1
3 changed files with 118 additions and 115 deletions

View File

@@ -1,15 +1,18 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { siteRoot, lang } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import MenuControl from '../menu-control';
import moment from 'moment'; import moment from 'moment';
import PropTypes from 'prop-types';
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
import { gettext, siteRoot, lang } from '../../utils/constants';
import { Utils } from '../../utils/utils';
moment.locale(lang); moment.locale(lang);
const propTypes = { const propTypes = {
isItemFreezed: PropTypes.bool.isRequired,
onMenuToggleClick: PropTypes.func.isRequired,
draft: PropTypes.object.isRequired, draft: PropTypes.object.isRequired,
isItemFreezed: PropTypes.bool.isRequired,
onFreezedItem: PropTypes.func.isRequired,
onUnfreezedItem: PropTypes.func.isRequired,
onDeleteHandler: PropTypes.func.isRequired,
onReviewHandler: PropTypes.func.isRequired,
}; };
class DraftListItem extends React.Component { class DraftListItem extends React.Component {
@@ -17,16 +20,17 @@ class DraftListItem extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
isMenuControlShow: false, isMenuIconShow: false,
highlight: '', isItemMenuShow: false,
highlight: false,
}; };
} }
onMouseEnter = () => { onMouseEnter = () => {
if (!this.props.isItemFreezed) { if (!this.props.isItemFreezed) {
this.setState({ this.setState({
isMenuControlShow: true, isMenuIconShow: true,
highlight: 'tr-highlight' highlight: true,
}); });
} }
} }
@@ -34,16 +38,40 @@ class DraftListItem extends React.Component {
onMouseLeave = () => { onMouseLeave = () => {
if (!this.props.isItemFreezed) { if (!this.props.isItemFreezed) {
this.setState({ this.setState({
isMenuControlShow: false, isMenuIconShow: false,
highlight: '' highlight: false,
}); });
} }
} }
onMenuToggleClick = (e) => { onDropdownToggleClick = (e) => {
e.nativeEvent.stopImmediatePropagation(); e.preventDefault();
let draft = this.props.draft; this.toggleOperationMenu(e);
this.props.onMenuToggleClick(e, draft); }
toggleOperationMenu = (e) => {
e.stopPropagation();
this.setState(
{isItemMenuShow: !this.state.isItemMenuShow }, () => {
if (this.state.isItemMenuShow) {
this.props.onFreezedItem();
} else {
this.setState({
highlight: false,
isMenuIconShow: false,
});
this.props.onUnfreezedItem();
}
}
);
}
onDeleteHandler = () => {
this.props.onDeleteHandler(this.props.draft);
}
onReviewHandler = () => {
this.props.onReviewHandler(this.props.draft);
} }
render() { render() {
@@ -59,7 +87,7 @@ class DraftListItem extends React.Component {
let iconUrl = Utils.getFileIconUrl(fileName); let iconUrl = Utils.getFileIconUrl(fileName);
return ( return (
<tr className={this.state.highlight} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}> <tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="text-center"><img src={iconUrl} width="24" alt='' /></td> <td className="text-center"><img src={iconUrl} width="24" alt='' /></td>
<td className="name" > <td className="name" >
<a href={draftUrl} target="_blank">{fileName}</a> <a href={draftUrl} target="_blank">{fileName}</a>
@@ -74,14 +102,23 @@ class DraftListItem extends React.Component {
} }
</td> </td>
<td className="update">{localTime}</td> <td className="update">{localTime}</td>
<td className="text-center cursor-pointer"> <td className="text-center">
{ {(this.props.draft.review_status !== 'open' && this.state.isMenuIconShow) && (
this.props.draft.review_status !== 'open' && <Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
<MenuControl <DropdownToggle
isShow={this.state.isMenuControlShow} tag="i"
onClick={this.onMenuToggleClick} className="fas fa-ellipsis-v attr-action-icon"
/> title={gettext('More Operations')}
} onClick={this.onDropdownToggleClick}
data-toggle="dropdown"
aria-expanded={this.state.isItemMenuShow}
/>
<DropdownMenu>
<DropdownItem onClick={this.onDeleteHandler}>{gettext('Delete')}</DropdownItem>
<DropdownItem onClick={this.onReviewHandler}>{gettext('Ask for review')}</DropdownItem>
</DropdownMenu>
</Dropdown>
)}
</td> </td>
</tr> </tr>
); );

View File

@@ -4,13 +4,28 @@ import { gettext } from '../../utils/constants';
import DraftListItem from './draft-list-item'; import DraftListItem from './draft-list-item';
const propTypes = { const propTypes = {
isItemFreezed: PropTypes.bool.isRequired,
draftList: PropTypes.array.isRequired, draftList: PropTypes.array.isRequired,
onMenuToggleClick: PropTypes.func.isRequired, onDeleteHandler: PropTypes.func.isRequired,
onReviewHandler: PropTypes.func.isRequired,
}; };
class DraftListView extends React.Component { class DraftListView extends React.Component {
constructor(props) {
super(props);
this.state = {
isItemFreezed: false,
};
}
onFreezedItem = () => {
this.setState({isItemFreezed: true});
}
onUnfreezedItem = () => {
this.setState({isItemFreezed: false});
}
render() { render() {
let drafts = this.props.draftList; let drafts = this.props.draftList;
return ( return (
@@ -31,8 +46,11 @@ class DraftListView extends React.Component {
<DraftListItem <DraftListItem
key={draft.id} key={draft.id}
draft={draft} draft={draft}
onMenuToggleClick={this.props.onMenuToggleClick} isItemFreezed={this.state.isItemFreezed}
isItemFreezed={this.props.isItemFreezed} onFreezedItem={this.onFreezedItem}
onUnfreezedItem={this.onUnfreezedItem}
onDeleteHandler={this.props.onDeleteHandler}
onReviewHandler={this.props.onReviewHandler}
/> />
); );
})} })}

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { Fragment } from 'react';
import { siteRoot, gettext } from '../../utils/constants'; import { siteRoot, gettext } from '../../utils/constants';
import editUtilties from '../../utils/editor-utilties'; import editUtilties from '../../utils/editor-utilties';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
@@ -6,38 +6,22 @@ import PropTypes from 'prop-types';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import DraftListView from '../../components/draft-list-view/draft-list-view'; import DraftListView from '../../components/draft-list-view/draft-list-view';
import DraftListMenu from '../../components/draft-list-view/draft-list-menu';
const propTypes = { const propTypes = {
updateDraftsList: PropTypes.func.isRequired,
isLoadingDraft: PropTypes.bool.isRequired, isLoadingDraft: PropTypes.bool.isRequired,
draftList: PropTypes.arrayOf(PropTypes.object), updateDraftsList: PropTypes.func.isRequired,
draftList: PropTypes.array.isRequired,
getDrafts: PropTypes.func.isRequired, getDrafts: PropTypes.func.isRequired,
}; };
class DraftContent extends React.Component { class DraftContent extends React.Component {
constructor(props) {
super(props);
this.state = {
isMenuShow: false,
menuPosition: {top:'', left: ''},
currentDraft: null,
isItemFreezed: false,
};
}
componentDidMount() { componentDidMount() {
this.props.getDrafts(); this.props.getDrafts();
document.addEventListener('click', this.onHideContextMenu);
} }
componentWillUnmount() { onDeleteHandler = (draft) => {
document.removeEventListener('click', this.onHideContextMenu); // let draft = this.state.currentDraft;
}
onDeleteHandler = () => {
let draft = this.state.currentDraft;
let draft_name = Utils.getFileName(draft.draft_file_path); let draft_name = Utils.getFileName(draft.draft_file_path);
editUtilties.deleteDraft(draft.id).then(res => { editUtilties.deleteDraft(draft.id).then(res => {
this.props.updateDraftsList(draft.id); this.props.updateDraftsList(draft.id);
@@ -51,6 +35,17 @@ class DraftContent extends React.Component {
}); });
} }
onReviewHandler = (draft) => {
editUtilties.createDraftReview(draft.id).then(res => {
const w = window.open();
w.location = siteRoot + 'drafts/review/' + res.data.id;
}).catch((error) => {
if (error.response.status == '409') {
toaster.danger(gettext('Review already exists.'));
}
});
}
onPublishHandler = () => { onPublishHandler = () => {
let draft = this.state.currentDraft; let draft = this.state.currentDraft;
let draft_name = Utils.getFileName(draft.draft_file_path); let draft_name = Utils.getFileName(draft.draft_file_path);
@@ -65,75 +60,28 @@ class DraftContent extends React.Component {
toaster.danger(msg_s); toaster.danger(msg_s);
}); });
} }
onReviewHandler = () => {
let draft = this.state.currentDraft;
editUtilties.createDraftReview(draft.id).then(res => {
const w = window.open();
w.location = siteRoot + 'drafts/review/' + res.data.id;
}).catch((error) => {
if (error.response.status == '409') {
toaster.danger(gettext('Review already exists.'));
}
});
}
onMenuToggleClick = (e, draft) => {
if (this.state.isMenuShow) {
this.onHideContextMenu();
} else {
this.onShowContextMenu(e, draft);
}
}
onShowContextMenu = (e, draft) => {
let left = e.clientX - 8*16;
let top = e.clientY + 10;
let position = {top: top, left: left};
this.setState({
isMenuShow: true,
menuPosition: position,
currentDraft: draft,
isItemFreezed: true
});
}
onHideContextMenu = () => {
this.setState({
isMenuShow: false,
currentDraft: null,
isItemFreezed: false
});
}
render() { render() {
return ( return (
<div className="cur-view-content"> <div className="cur-view-content">
{this.props.isLoadingDraft && <Loading /> } {this.props.isLoadingDraft && <Loading />}
{(!this.props.isLoadingDraft && this.props.draftList.length !==0) && {!this.props.isLoadingDraft && (
<DraftListView <Fragment>
draftList={this.props.draftList} {this.props.draftList.length === 0 && (
isItemFreezed={this.state.isItemFreezed} <div className="message empty-tip">
onMenuToggleClick={this.onMenuToggleClick} <h2>{gettext('No draft yet')}</h2>
/> <p>{gettext('Draft is a way to let you collaborate with others on files. You can create a draft from a file, edit the draft and then ask for a review. The original file will be updated only after the draft be reviewed.')}</p>
} </div>
{(!this.props.isLoadingDraft && this.props.draftList.length === 0) && )}
<div className="message empty-tip"> {this.props.draftList.length !==0 && (
<h2>{gettext('No draft yet')}</h2> <DraftListView
<p>{gettext('Draft is a way to let you collaborate with others on files. You can create a draft from a file, edit the draft and then ask for a review. The original file will be updated only after the draft be reviewed.')}</p> draftList={this.props.draftList}
</div> onDeleteHandler={this.onDeleteHandler}
} onReviewHandler={this.onReviewHandler}
{this.state.isMenuShow && />
<DraftListMenu )}
isMenuShow={this.state.isMenuShow} </Fragment>
currentDraft={this.state.currentDraft} )}
menuPosition={this.state.menuPosition}
onPublishHandler={this.onPublishHandler}
onDeleteHandler={this.onDeleteHandler}
onReviewHandler={this.onReviewHandler}
/>
}
</div> </div>
); );
} }