1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 23:20:51 +00:00

decrease comments request

This commit is contained in:
Michael An
2019-05-30 17:30:59 +08:00
parent f9953d1be4
commit 8d173c9996
2 changed files with 71 additions and 116 deletions

View File

@@ -5,15 +5,14 @@ import { Button, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 're
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { gettext, draftFilePath, draftRepoID } from '../../utils/constants'; import { gettext, draftFilePath, draftRepoID } from '../../utils/constants';
import Loading from '../../components/loading.js'; import Loading from '../../components/loading.js';
import reviewComment from '../../models/review-comment.js';
import { username } from '../../utils/constants.js'; import { username } from '../../utils/constants.js';
import '../../css/review-comments.css'; import '../../css/review-comments.css';
const commentPropTypes = { const commentPropTypes = {
getCommentsNumber: PropTypes.func.isRequired, listComments: PropTypes.func.isRequired,
inResizing: PropTypes.bool.isRequired, inResizing: PropTypes.bool.isRequired,
commentsNumber: PropTypes.number, commentsList: PropTypes.array.isRequired,
scrollToQuote: PropTypes.func.isRequired scrollToQuote: PropTypes.func.isRequired
}; };
@@ -22,7 +21,6 @@ class ReviewComments extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
commentsList: [],
inResizing: false, inResizing: false,
commentFooterHeight: 25, commentFooterHeight: 25,
showResolvedComment: true, showResolvedComment: true,
@@ -30,23 +28,6 @@ class ReviewComments extends React.Component {
}; };
} }
listComments = (scroll) => {
seafileAPI.listComments(draftRepoID, draftFilePath).then((response) => {
let commentList = [];
response.data.comments.forEach(item => {
let commentItem = new reviewComment(item);
commentList.push(commentItem);
});
this.setState({ commentsList: commentList });
if (scroll) {
let that = this;
setTimeout(() => {
that.refs.commentsList.scrollTo(0, 10000);
}, 100);
}
});
}
handleCommentChange = (event) => { handleCommentChange = (event) => {
this.setState({ comment: event.target.value }); this.setState({ comment: event.target.value });
} }
@@ -55,8 +36,7 @@ class ReviewComments extends React.Component {
let comment = this.state.comment.trim(); let comment = this.state.comment.trim();
if (comment.length > 0) { if (comment.length > 0) {
seafileAPI.postComment(draftRepoID, draftFilePath, comment).then(() => { seafileAPI.postComment(draftRepoID, draftFilePath, comment).then(() => {
this.listComments(true); this.props.listComments();
this.props.getCommentsNumber();
}); });
this.setState({ comment: '' }); this.setState({ comment: '' });
} }
@@ -64,15 +44,13 @@ class ReviewComments extends React.Component {
resolveComment = (event) => { resolveComment = (event) => {
seafileAPI.updateComment(draftRepoID, event.target.id, 'true').then((res) => { seafileAPI.updateComment(draftRepoID, event.target.id, 'true').then((res) => {
this.props.getCommentsNumber(); this.props.listComments();
this.listComments();
}); });
} }
editComment = (commentID, newComment) => { editComment = (commentID, newComment) => {
seafileAPI.updateComment(draftRepoID, commentID, null, null, newComment).then((res) => { seafileAPI.updateComment(draftRepoID, commentID, null, null, newComment).then((res) => {
this.props.getCommentsNumber(); this.props.listComments();
this.listComments();
}); });
} }
@@ -82,8 +60,7 @@ class ReviewComments extends React.Component {
deleteComment = (event) => { deleteComment = (event) => {
seafileAPI.deleteComment(draftRepoID, event.target.id).then((res) => { seafileAPI.deleteComment(draftRepoID, event.target.id).then((res) => {
this.props.getCommentsNumber(); this.props.listComments();
this.listComments();
}); });
} }
@@ -117,20 +94,18 @@ class ReviewComments extends React.Component {
this.setState({ comment: '' }); this.setState({ comment: '' });
} }
componentWillMount() {
this.listComments();
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (this.props.commentsNumber !== nextProps.commentsNumber) { if (this.props.commentsList.length < nextProps.commentsList.length) {
this.listComments(); let that = this;
setTimeout(() => {
that.refs.commentsList.scrollTo(0, 10000);
}, 100);
} }
} }
render() { render() {
const onResizeMove = this.state.inResizing ? this.onResizeMouseMove : null; const onResizeMove = this.state.inResizing ? this.onResizeMouseMove : null;
const { commentsNumber } = this.props; const { commentsList } = this.props;
const { commentsList } = this.state;
return ( return (
<div className={(this.state.inResizing || this.props.inResizing)? <div className={(this.state.inResizing || this.props.inResizing)?
'seafile-comment seafile-comment-resizing' : 'seafile-comment'} 'seafile-comment seafile-comment-resizing' : 'seafile-comment'}
@@ -148,17 +123,13 @@ class ReviewComments extends React.Component {
</div> </div>
</div> </div>
<div style={{height:(100 - this.state.commentFooterHeight)+'%'}}> <div style={{height:(100 - this.state.commentFooterHeight)+'%'}}>
{commentsNumber == 0 && {commentsList.length === 0 &&
<div className="seafile-comment-list"> <div className="seafile-comment-list">
<div className="comment-vacant">{gettext('No comment yet.')}</div> <div className="comment-vacant">{gettext('No comment yet.')}</div>
</div> </div>
} }
{(commentsList.length === 0 && commentsNumber > 0) &&
<div className={'seafile-comment-list'}><Loading/></div>
}
{commentsList.length > 0 &&
<ul className="seafile-comment-list" ref='commentsList'> <ul className="seafile-comment-list" ref='commentsList'>
{(commentsList.length > 0 && commentsNumber > 0) && {(commentsList.length > 0) &&
commentsList.map((item, index) => { commentsList.map((item, index) => {
return ( return (
<CommentItem <CommentItem
@@ -174,7 +145,6 @@ class ReviewComments extends React.Component {
}) })
} }
</ul> </ul>
}
</div> </div>
<div className="seafile-comment-footer" style={{height:this.state.commentFooterHeight+'%'}}> <div className="seafile-comment-footer" style={{height:this.state.commentFooterHeight+'%'}}>
<div className="seafile-comment-row-resize" onMouseDown={this.onResizeMouseDown}></div> <div className="seafile-comment-row-resize" onMouseDown={this.onResizeMouseDown}></div>
@@ -186,9 +156,7 @@ class ReviewComments extends React.Component {
onChange={this.handleCommentChange} onChange={this.handleCommentChange}
clos="100" rows="3" warp="virtual" clos="100" rows="3" warp="virtual"
></textarea> ></textarea>
<Button className="comment-btn" color="success" <Button className="comment-btn" color="success" size="sm" onClick={this.submitComment}>{gettext('Submit')}</Button>
size="sm" onClick={this.submitComment}>
{gettext('Submit')}</Button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -21,6 +21,7 @@ import classnames from 'classnames';
import HistoryList from './pages/review/history-list'; import HistoryList from './pages/review/history-list';
import { Value, Document, Block } from 'slate'; import { Value, Document, Block } from 'slate';
import ModalPortal from './components/modal-portal'; import ModalPortal from './components/modal-portal';
import reviewComment from './models/review-comment.js';
import './assets/css/fa-solid.css'; import './assets/css/fa-solid.css';
import './assets/css/fa-regular.css'; import './assets/css/fa-regular.css';
@@ -45,11 +46,10 @@ class Draft extends React.Component {
isShowDiff: true, isShowDiff: true,
showDiffTip: false, showDiffTip: false,
activeTab: 'reviewInfo', activeTab: 'reviewInfo',
commentsNumber: null, commentsList: [],
changedNodes: [], changedNodes: [],
originRepoName: '', originRepoName: '',
isShowCommentDialog: false, isShowCommentDialog: false,
unresolvedComments: 0,
activeItem: null, activeItem: null,
historyList: [], historyList: [],
showReviewerDialog: false, showReviewerDialog: false,
@@ -196,25 +196,16 @@ class Draft extends React.Component {
} }
onHistoryListChange = (historyList) => { onHistoryListChange = (historyList) => {
this.setState({ this.setState({historyList: historyList });
historyList: historyList
});
} }
getCommentsNumber = () => { listComments = () => {
seafileAPI.listComments(draftRepoID, draftFilePath).then((res) => { seafileAPI.listComments(draftRepoID, draftFilePath).then((res) => {
let number = res.data.total_count; let commentsList = [];
let comments = res.data.comments; res.data.comments.forEach((item) => {
let unresolvedComments = 0; commentsList.push(new reviewComment(item));
for (let i = 0; i < res.data.total_count; i++) {
if (comments[i].resolved === false) {
unresolvedComments++;
}
}
this.setState({
commentsNumber: number,
unresolvedComments: unresolvedComments,
}); });
this.setState({ commentsList: commentsList });
}); });
} }
@@ -226,7 +217,7 @@ class Draft extends React.Component {
} }
onCommentAdded = () => { onCommentAdded = () => {
this.getCommentsNumber(); this.listComments();
this.toggleCommentDialog(); this.toggleCommentDialog();
} }
@@ -238,9 +229,7 @@ class Draft extends React.Component {
getOriginRepoInfo = () => { getOriginRepoInfo = () => {
seafileAPI.getRepoInfo(draftRepoID).then((res) => { seafileAPI.getRepoInfo(draftRepoID).then((res) => {
this.setState({ this.setState({ originRepoName: res.data.repo_name });
originRepoName: res.data.repo_name
});
}); });
} }
@@ -488,6 +477,7 @@ class Draft extends React.Component {
} }
showNavItem = (showTab) => { showNavItem = (showTab) => {
const commentsNumber = this.state.commentsList.length;
switch(showTab) { switch(showTab) {
case 'info': case 'info':
return ( return (
@@ -508,7 +498,7 @@ class Draft extends React.Component {
onClick={() => {this.tabItemClick('comments');}} onClick={() => {this.tabItemClick('comments');}}
> >
<i className="fa fa-comments"></i> <i className="fa fa-comments"></i>
{this.state.commentsNumber > 0 && <div className='comments-number'>{this.state.commentsNumber}</div>} {commentsNumber > 0 && <div className='comments-number'>{commentsNumber}</div>}
</NavLink> </NavLink>
</NavItem> </NavItem>
); );
@@ -662,14 +652,11 @@ class Draft extends React.Component {
this.setState({ rightPartWidth: rate }); this.setState({ rightPartWidth: rate });
}; };
componentWillMount() { componentDidMount() {
this.getCommentsNumber();
this.listReviewers();
this.getOriginRepoInfo(); this.getOriginRepoInfo();
this.getDraftInfo(); this.getDraftInfo();
} this.listReviewers();
this.listComments();
componentDidMount() {
this.initialContent(); this.initialContent();
document.addEventListener('selectionchange', this.setBtnPosition); document.addEventListener('selectionchange', this.setBtnPosition);
} }
@@ -744,12 +731,13 @@ class Draft extends React.Component {
} }
render() { render() {
const { draftInfo, reviewers, originRepoName } = this.state;
const onResizeMove = this.state.inResizing ? this.onResizeMouseMove : null; const onResizeMove = this.state.inResizing ? this.onResizeMouseMove : null;
const draftLink = siteRoot + 'lib/' + draftRepoID + '/file' + draftFilePath + '?mode=edit'; const draftLink = siteRoot + 'lib/' + draftRepoID + '/file' + draftFilePath + '?mode=edit';
const freezePublish = (this.state.freezePublish || draftStatus === 'published') ? true : false; const freezePublish = (this.state.freezePublish || draftStatus === 'published') ? true : false;
const canPublish = !this.state.freezePublish && draftFileExists && filePermission == 'rw'; const canPublish = !this.state.freezePublish && draftFileExists && filePermission == 'rw';
const time = moment(this.state.draftInfo.mtime * 1000).format('YYYY-MM-DD HH:mm'); const time = moment(draftInfo.mtime * 1000).format('YYYY-MM-DD HH:mm');
const url = `${siteRoot}profile/${encodeURIComponent(this.state.draftInfo.last_modifier_email)}/`; const url = `${siteRoot}profile/${encodeURIComponent(draftInfo.last_modifier_email)}/`;
return( return(
<div className="wrapper"> <div className="wrapper">
<div id="header" className="header review"> <div id="header" className="header review">
@@ -762,9 +750,9 @@ class Draft extends React.Component {
<span className="file-name">{draftFileName}</span> <span className="file-name">{draftFileName}</span>
<span className="mx-2 file-review">{gettext('Review')}</span> <span className="mx-2 file-review">{gettext('Review')}</span>
</div> </div>
{(!freezePublish && this.state.draftInfo.mtime) && {(!freezePublish && draftInfo.mtime) &&
<div className="last-modification"> <div className="last-modification">
<a href={url}>{this.state.draftInfo.last_modifier_name}</a><span className="mx-1">{time}</span> <a href={url}>{draftInfo.last_modifier_name}</a><span className="mx-1">{time}</span>
</div> </div>
} }
</div> </div>
@@ -777,20 +765,12 @@ class Draft extends React.Component {
</a> </a>
} }
{canPublish && {canPublish &&
<button <button className='btn btn-success file-operation-btn' title={gettext('Publish draft')} onClick={this.onPublishDraft}>
className='btn btn-success file-operation-btn'
title={gettext('Publish draft')}
onClick={this.onPublishDraft}
>
{gettext('Publish')} {gettext('Publish')}
</button> </button>
} }
{freezePublish && {freezePublish &&
<button <button className='btn btn-success file-operation-btn' title={gettext('Published')} disabled>
className='btn btn-success file-operation-btn'
title={gettext('Published')}
disabled
>
{gettext('Published')} {gettext('Published')}
</button> </button>
} }
@@ -817,25 +797,23 @@ class Draft extends React.Component {
<TabPane tabId="reviewInfo"> <TabPane tabId="reviewInfo">
<div className="review-side-panel-body"> <div className="review-side-panel-body">
<SidePanelReviewers <SidePanelReviewers
reviewers={this.state.reviewers} reviewers={reviewers}
toggleAddReviewerDialog={this.toggleAddReviewerDialog}/> toggleAddReviewerDialog={this.toggleAddReviewerDialog}/>
<SidePanelAuthor/> <SidePanelAuthor/>
{draftFileExists && {draftFileExists && <UnresolvedComments commentsList={this.state.commentsList}/>}
<UnresolvedComments number={this.state.unresolvedComments}/>
}
{(this.state.isShowDiff === true && this.state.changedNodes.length > 0) && {(this.state.isShowDiff === true && this.state.changedNodes.length > 0) &&
<SidePanelChanges <SidePanelChanges
changedNumber={this.state.changedNodes.length} changedNumber={this.state.changedNodes.length}
scrollToChangedNode={this.scrollToChangedNode}/> scrollToChangedNode={this.scrollToChangedNode}/>
} }
<SidePanelOrigin originRepoName={this.state.originRepoName} draftInfo={this.state.draftInfo}/> <SidePanelOrigin originRepoName={originRepoName} draftInfo={draftInfo}/>
</div> </div>
</TabPane> </TabPane>
<TabPane tabId="comments" className="comments"> <TabPane tabId="comments" className="comments">
<ReviewComments <ReviewComments
scrollToQuote={this.scrollToQuote} scrollToQuote={this.scrollToQuote}
getCommentsNumber={this.getCommentsNumber} listComments={this.listComments}
commentsNumber={this.state.commentsNumber} commentsList={this.state.commentsList}
inResizing={false} inResizing={false}
/> />
</TabPane> </TabPane>
@@ -859,7 +837,7 @@ class Draft extends React.Component {
showReviewerDialog={this.state.showReviewerDialog} showReviewerDialog={this.state.showReviewerDialog}
toggleAddReviewerDialog={this.toggleAddReviewerDialog} toggleAddReviewerDialog={this.toggleAddReviewerDialog}
draftID={draftID} draftID={draftID}
reviewers={this.state.reviewers} reviewers={reviewers}
/> />
</ModalPortal> </ModalPortal>
} }
@@ -967,11 +945,20 @@ class UnresolvedComments extends React.Component {
} }
render() { render() {
const { commentsList } = this.props;
let unresolvedNumber = 0;
if (commentsList) {
for (let i = 0, count = commentsList.length; i < count; i++) {
if (commentsList[i].resolved === false) {
unresolvedNumber++;
}
}
}
return ( return (
<div className="review-side-panel-item"> <div className="review-side-panel-item">
<div className="review-side-panel-header">{gettext('Comments')}</div> <div className="review-side-panel-header">{gettext('Comments')}</div>
<div className="changes-info"> <div className="changes-info">
<span>{gettext('Unresolved comments:')}{' '}{this.props.number}</span> <span>{gettext('Unresolved comments:')}{' '}{unresolvedNumber}</span>
</div> </div>
</div> </div>
); );
@@ -979,7 +966,7 @@ class UnresolvedComments extends React.Component {
} }
const UnresolvedCommentsPropTypes = { const UnresolvedCommentsPropTypes = {
number: PropTypes.number.isRequired commentsList: PropTypes.array.isRequired,
}; };
UnresolvedComments.propTypes = UnresolvedCommentsPropTypes; UnresolvedComments.propTypes = UnresolvedCommentsPropTypes;