[mobile] Make view current comments, fixed change comment

This commit is contained in:
JuliaSvinareva 2021-03-10 21:08:59 +03:00
parent c9e5a41954
commit f5d48e6492
5 changed files with 233 additions and 85 deletions

View file

@ -58,6 +58,8 @@ class CommentsController extends Component {
api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this)); api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this));
api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this)); api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this));
api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this)); api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this));
api.asc_registerCallback('asc_onShowComment', this.changeShowComments.bind(this));
api.asc_registerCallback('asc_onHideComment', this.hideComments.bind(this));
}); });
Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse
@ -97,57 +99,58 @@ class CommentsController extends Component {
this.removeComment(data[i]); this.removeComment(data[i]);
} }
} }
changeShowComments (id) {
this.storeComments.changeShowComment(id);
}
hideComments () {
//Common.Notifications.trigger('closeviewcomment');
}
changeCommentData (id, data) { changeCommentData (id, data) {
let date = null; const changeComment = {};
let replies = null;
let repliesCount = 0; const date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime())));
let user = this.usersStore.searchUserById(data.asc_getUserId());
changeComment.comment = data.asc_getText();
changeComment.userId = data.asc_getUserId();
changeComment.userName = data.asc_getUserName();
changeComment.userColor = (user) ? user.asc_getColor() : null;
changeComment.resolved = data.asc_getSolved();
changeComment.quote = data.asc_getQuoteText();
changeComment.time = date.getTime();
changeComment.date = dateToLocaleTimeString(date);
changeComment.editable = this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId);
changeComment.removable = this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId);
let dateReply = null; let dateReply = null;
const replies = [];
const comment = this.storeComments.findComment(id); const repliesCount = data.asc_getRepliesCount();
for (let i = 0; i < repliesCount; ++i) {
if (comment) { dateReply = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) :
((data.asc_getReply(i).asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getReply(i).asc_getTime())));
date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) : user = this.usersStore.searchUserById(data.asc_getReply(i).asc_getUserId());
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime()))); const userName = data.asc_getReply(i).asc_getUserName();
replies.push({
let user = this.usersStore.searchUserById(data.asc_getUserId()); ind: i,
userId: data.asc_getReply(i).asc_getUserId(),
comment.comment = data.asc_getText(); userName: userName,
comment.userId = data.asc_getUserId(); userColor: (user) ? user.asc_getColor() : null,
comment.userName = data.asc_getUserName(); date: dateToLocaleTimeString(dateReply),
comment.userColor = (user) ? user.asc_getColor() : null; reply: data.asc_getReply(i).asc_getText(),
comment.resolved = data.asc_getSolved(); time: dateReply.getTime(),
comment.quote = data.asc_getQuoteText(); userInitials: this.usersStore.getInitials(userName),
comment.time = date.getTime(); editable: this.appOptions.canEditComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId),
comment.date = dateToLocaleTimeString(date); removable: this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId)
comment.editable = this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId); });
comment.removable = this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId);
replies = [];
repliesCount = data.asc_getRepliesCount();
for (let i = 0; i < repliesCount; ++i) {
dateReply = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) :
((data.asc_getReply(i).asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getReply(i).asc_getTime())));
user = this.usersStore.searchUserById(data.asc_getReply(i).asc_getUserId());
const userName = data.asc_getReply(i).asc_getUserName();
replies.push({
ind: i,
userId: data.asc_getReply(i).asc_getUserId(),
userName: userName,
userColor: (user) ? user.asc_getColor() : null,
date: dateToLocaleTimeString(dateReply),
reply: data.asc_getReply(i).asc_getText(),
time: dateReply.getTime(),
userInitials: this.usersStore.getInitials(userName),
editable: this.appOptions.canEditComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId),
removable: this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId)
});
}
comment.replies = replies;
} }
changeComment.replies = replies;
this.props.storeComments.changeComment(id, changeComment);
} }
onFilterChange (filter) { onFilterChange (filter) {
this.storeComments.changeFilter(filter); this.storeComments.changeFilter(filter);
@ -308,7 +311,7 @@ class EditCommentController extends Component {
var reply = comment.replies; var reply = comment.replies;
if (reply && reply.length > 0) { if (reply && reply.length > 0) {
reply.forEach((reply) => { reply.forEach((reply) => {
var addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); var addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) { if (addReply) {
addReply.asc_putText(reply.reply); addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time))); addReply.asc_putTime(utcDateToString(new Date(reply.time)));
@ -325,11 +328,12 @@ class EditCommentController extends Component {
} }
} }
onEditComment (comment, text) { onEditComment (comment, text) {
comment.comment = text.trim(); const changeComment = {...comment};
changeComment.comment = text.trim();
const user = this.props.users.currentUser; const user = this.props.users.currentUser;
comment.userid = user.asc_getIdOriginal(); changeComment.userid = user.asc_getIdOriginal();
comment.username = user.asc_getUserName(); changeComment.username = user.asc_getUserName();
this.onChangeComment(comment); this.onChangeComment(changeComment);
} }
onAddReply (comment, replyVal) { onAddReply (comment, replyVal) {
let reply = null; let reply = null;
@ -386,10 +390,13 @@ class EditCommentController extends Component {
onEditReply (comment, reply, textReply) { onEditReply (comment, reply, textReply) {
const currentUser = this.props.users.currentUser; const currentUser = this.props.users.currentUser;
const indReply = reply.ind; const indReply = reply.ind;
comment.replies[indReply].reply = textReply; const changeComment = {...comment};
comment.replies[indReply].userid = currentUser.asc_getIdOriginal(); changeComment.replies = [...comment.replies];
comment.replies[indReply].username = currentUser.asc_getUserName(); changeComment.replies[indReply] = {...reply};
this.onChangeComment(comment); changeComment.replies[indReply].reply = textReply;
changeComment.replies[indReply].userid = currentUser.asc_getIdOriginal();
changeComment.replies[indReply].username = currentUser.asc_getUserName();
this.onChangeComment(changeComment);
} }
render() { render() {
const storeComments = this.props.storeComments; const storeComments = this.props.storeComments;
@ -418,14 +425,18 @@ class ViewCommentsController extends Component {
Common.Notifications.on('viewcomment', () => { Common.Notifications.on('viewcomment', () => {
this.setState({isOpenViewCurComments: true}); this.setState({isOpenViewCurComments: true});
}); });
Common.Notifications.on('closeviewcomment', () => {
this.closeViewCurComments();
});
} }
closeViewCurComments () { closeViewCurComments () {
f7.sheet.close('#view-comment-sheet');
this.setState({isOpenViewCurComments: false}); this.setState({isOpenViewCurComments: false});
} }
onResolveComment (comment) { onResolveComment (comment) {
let reply = null, let reply = null,
addReply = null, addReply = null,
ascComment = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); ascComment = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment && comment) { if (ascComment && comment) {
ascComment.asc_putText(comment.comment); ascComment.asc_putText(comment.comment);
@ -444,7 +455,7 @@ class ViewCommentsController extends Component {
reply = comment.replies; reply = comment.replies;
if (reply && reply.length > 0) { if (reply && reply.length > 0) {
reply.forEach((reply) => { reply.forEach((reply) => {
addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) { if (addReply) {
addReply.asc_putText(reply.reply); addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time))); addReply.asc_putTime(utcDateToString(new Date(reply.time)));
@ -546,7 +557,11 @@ class ViewCommentsController extends Component {
return( return(
<Fragment> <Fragment>
{this.props.allComments && <ViewComments onCommentMenuClick={this.onCommentMenuClick} onResolveComment={this.onResolveComment} />} {this.props.allComments && <ViewComments onCommentMenuClick={this.onCommentMenuClick} onResolveComment={this.onResolveComment} />}
{this.state.isOpenViewCurComments && <ViewCurrentComments opened={this.state.isOpenViewCurComments} closeCurComments={this.closeViewCurComments} />} {this.state.isOpenViewCurComments && <ViewCurrentComments opened={this.state.isOpenViewCurComments}
closeCurComments={this.closeViewCurComments}
onCommentMenuClick={this.onCommentMenuClick}
onResolveComment={this.onResolveComment}
/>}
</Fragment> </Fragment>
) )
} }

View file

@ -9,8 +9,12 @@ export class storeComments {
filter: observable, filter: observable,
groupCollectionFilter: observable, groupCollectionFilter: observable,
showComments: observable,
changeShowComment: action,
addComment: action, addComment: action,
removeComment: action, removeComment: action,
changeComment: action,
changeFilter: action, changeFilter: action,
sortComments: computed, sortComments: computed,
@ -29,6 +33,14 @@ export class storeComments {
filter = undefined; filter = undefined;
groupCollectionFilter = []; // for sse groupCollectionFilter = []; // for sse
showComments = [];
changeShowComment (uid) {
this.showComments.length = 0;
uid.forEach((item) => {
this.showComments.push(this.findComment(item));
});
}
addComment (comment) { addComment (comment) {
comment.groupName ? this.addCommentToGroupCollection(comment) : this.addCommentToCollection(comment); comment.groupName ? this.addCommentToGroupCollection(comment) : this.addCommentToCollection(comment);
} }
@ -81,6 +93,23 @@ export class storeComments {
} }
} }
changeComment (id, changeComment) {
const comment = this.findComment(id);
if (comment) {
comment.comment = changeComment.comment;
comment.userId = changeComment.userId;
comment.userName = changeComment.userName;
comment.userColor = changeComment.userColor;
comment.resolved = changeComment.resolved;
comment.quote = changeComment.quote;
comment.time = changeComment.time;
comment.date = changeComment.date;
comment.editable = changeComment.editable;
comment.removable = changeComment.removable;
comment.replies = changeComment.replies;
}
}
changeFilter (filter) { changeFilter (filter) {
let comments = []; let comments = [];
this.filter = filter; this.filter = filter;

View file

@ -4,6 +4,18 @@ import { f7, Popup, Sheet, Popover, Page, Toolbar, Navbar, NavLeft, NavRight, Na
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import {Device} from '../../../utils/device'; import {Device} from '../../../utils/device';
// Utils
const sliceQuote = (text) => {
if (text) {
let sliced = text.slice(0, 100);
if (sliced.length < text.length) {
sliced += '...';
return sliced;
}
return text;
}
};
// Add comment // Add comment
const AddCommentPopup = inject("storeComments")(observer(props => { const AddCommentPopup = inject("storeComments")(observer(props => {
@ -533,16 +545,6 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
const viewMode = !storeAppOptions.canComments; const viewMode = !storeAppOptions.canComments;
const comments = storeComments.sortComments; const comments = storeComments.sortComments;
const sliceQuote = (text) => {
if (text) {
let sliced = text.slice(0, 100);
if (sliced.length < text.length) {
sliced += '...';
return sliced;
}
return text;
}
};
const [clickComment, setComment] = useState(); const [clickComment, setComment] = useState();
const [commentActionsOpened, openActionComment] = useState(false); const [commentActionsOpened, openActionComment] = useState(false);
@ -633,18 +635,105 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
const _ViewComments = inject('storeComments', 'storeAppOptions')(observer(ViewComments)); const _ViewComments = inject('storeComments', 'storeAppOptions')(observer(ViewComments));
const CommentList = () => { const CommentList = inject("storeComments", "storeAppOptions")(observer(({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment}) => {
return (
<List>
</List>
)
};
const ViewCommentSheet = ({closeCurComments}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true}); const _t = t('Common.Collaboration', {returnObjects: true});
const isAndroid = Device.android;
const viewMode = !storeAppOptions.canComments;
const comments = storeComments.showComments;
const [currentIndex, setCurrentIndex] = useState(0);
const comment = comments[currentIndex];
const [commentActionsOpened, openActionComment] = useState(false);
const [reply, setReply] = useState();
const [replyActionsOpened, openActionReply] = useState(false);
return (
<Fragment>
<Toolbar position='bottom'>
<Link className='btn-add-reply' href='#'>{_t.textAddReply}</Link>
<div className='comment-navigation row'>
<Link href='#'><Icon slot='media' icon='icon-prev'/></Link>
<Link href='#'><Icon slot='media' icon='icon-next'/></Link>
</div>
</Toolbar>
<Page className='page-current-comment'>
<List className='comment-list'>
<ListItem>
<div slot='header' className='comment-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${comment.userColor ? comment.userColor : '#cfcfcf'}`}}>{comment.userInitials}</div>}
<div>
<div className='user-name'>{comment.userName}</div>
<div className='comment-date'>{comment.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'} /></div>
<div className='comment-menu'
onClick={() => {openActionComment(true);}}
><Icon icon='icon-menu-comment'/></div>
</div>
}
</div>
<div slot='footer'>
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
<div className='comment-text'><pre>{comment.comment}</pre></div>
{comment.replies.length > 0 &&
<ul className='reply-list'>
{comment.replies.map((reply, indexReply) => {
return (
<li key={`reply-${indexReply}`}
className='reply-item'
>
<div className='item-content'>
<div className='item-inner'>
<div className='item-title'>
<div slot='header' className='reply-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${reply.userColor ? reply.userColor : '#cfcfcf'}`}}>{reply.userInitials}</div>}
<div>
<div className='user-name'>{reply.userName}</div>
<div className='reply-date'>{reply.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='reply-menu'
onClick={() => {setReply(reply); openActionReply(true);}}
>
<Icon icon='icon-menu-comment'/>
</div>
</div>
}
</div>
<div slot='footer'>
<div className='reply-text'><pre>{reply.reply}</pre></div>
</div>
</div>
</div>
</div>
</li>
)
})}
</ul>
}
</div>
</ListItem>
</List>
<CommentActions comment={comment} onCommentMenuClick={onCommentMenuClick} opened={commentActionsOpened} openActionComment={openActionComment}/>
<ReplyActions comment={comment} reply={reply} onCommentMenuClick={onCommentMenuClick} opened={replyActionsOpened} openActionReply={openActionReply}/>
</Page>
</Fragment>
)
}));
const ViewCommentSheet = ({closeCurComments, onCommentMenuClick, onResolveComment}) => {
useEffect(() => { useEffect(() => {
f7.sheet.open('#view-comment-sheet'); f7.sheet.open('#view-comment-sheet');
}); });
@ -681,7 +770,6 @@ const ViewCommentSheet = ({closeCurComments}) => {
const swipeEnd = parseInt(touchObj.clientY); const swipeEnd = parseInt(touchObj.clientY);
const dist = swipeEnd - stateStartY; const dist = swipeEnd - stateStartY;
if (isNeedClose) { if (isNeedClose) {
f7.sheet.close('#view-comment-sheet');
closeCurComments(); closeCurComments();
} else if (stateHeight === '90%' && dist > 20) { } else if (stateHeight === '90%' && dist > 20) {
setHeight('45%'); setHeight('45%');
@ -689,17 +777,10 @@ const ViewCommentSheet = ({closeCurComments}) => {
}; };
return ( return (
<Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}> <Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}>
<Toolbar position='bottom'>
<Link className='btn-add-reply' href='#'>{_t.textAddReply}</Link>
<div className='comment-navigation row'>
<Link href='#'><Icon slot='media' icon='icon-prev'/></Link>
<Link href='#'><Icon slot='media' icon='icon-next'/></Link>
</div>
</Toolbar>
<div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}> <div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
<Icon icon='icon-swipe'/> <Icon icon='icon-swipe'/>
</div> </div>
<CommentList /> <CommentList onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment}/>
</Sheet> </Sheet>
) )
}; };

View file

@ -154,4 +154,24 @@
} }
} }
} }
}
.page-current-comment {
position: relative;
.page-content {
background-color: @white;
}
.comment-list {
ul {
&:before, &:after {
content: none;
}
.item-content .item-inner {
padding-top: 0;
.reply-list .item-content .item-inner {
padding-top: 13px;
}
}
}
}
} }

View file

@ -7,4 +7,7 @@ i.icon {
height: 24px; height: 24px;
.encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" /><path d="M5 0H14V5H5V0Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" /></svg>'); .encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" /><path d="M5 0H14V5H5V0Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" /></svg>');
} }
&.icon-prev:after, &.icon-next:after {
content: none;
}
} }