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:
@@ -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>
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user