web-apps/apps/common/mobile/lib/controller/collaboration/Comments.jsx

464 lines
20 KiB
JavaScript

import React, {Component, Fragment} from 'react';
import { inject, observer } from "mobx-react";
import { f7 } from 'framework7-react';
import {Device} from '../../../../../common/mobile/utils/device';
import { withTranslation} from 'react-i18next';
import {AddComment, EditComment, ViewComments} from '../../view/collaboration/Comments';
// utils
const timeZoneOffsetInMs = (new Date()).getTimezoneOffset() * 60000;
const utcDateToString = (date) => {
if (Object.prototype.toString.call(date) === '[object Date]')
return (date.getTime() - timeZoneOffsetInMs).toString();
return '';
};
const ooDateToString = (date) => {
if (Object.prototype.toString.call(date) === '[object Date]')
return (date.getTime()).toString();
return '';
};
const stringOOToLocalDate = (date) => {
if (typeof date === 'string')
return parseInt(date);
return 0;
};
const stringUtcToLocalDate = (date) => {
if (typeof date === 'string')
return parseInt(date) + timeZoneOffsetInMs;
return 0;
};
const dateToLocaleTimeString = (date) => {
const format = (date) => {
let hours = date.getHours();
let minutes = date.getMinutes();
let ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
return hours + ':' + minutes + ' ' + ampm;
};
// MM/dd/yyyy hh:mm AM
return (date.getMonth() + 1) + '/' + (date.getDate()) + '/' + date.getFullYear() + ' ' + format(date);
};
//end utils
class CommentsController extends Component {
constructor(props) {
super(props);
this.usersStore = this.props.users;
this.appOptions = this.props.storeAppOptions;
this.storeComments = this.props.storeComments;
Common.Notifications.on('engineCreated', api => {
api.asc_registerCallback('asc_onAddComment', this.addComment.bind(this));
api.asc_registerCallback('asc_onAddComments', this.addComments.bind(this));
api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this));
api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this));
api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this));
});
Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse
Common.Notifications.on('configOptionsFill', () => {
this.curUserId = this.appOptions.user.id;
});
}
addComment (id, data) {
const comment = this.readSDKComment(id, data);
if (comment) {
this.storeComments.addComment(comment);
}
}
addComments (data) {
for (let i = 0; i < data.length; ++i) {
const comment = this.readSDKComment(data[i].asc_getId(), data[i]);
this.storeComments.addComment(comment);
}
}
removeComment (id) {
this.storeComments.removeComment(id);
}
removeComments (data) {
for (let i = 0; i < data.length; i++) {
this.removeComment(data[i]);
}
}
changeCommentData (id, data) {
let date = null;
let replies = null;
let repliesCount = 0;
let dateReply = null;
const comment = this.storeComments.findComment(id);
if (comment) {
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());
comment.comment = data.asc_getText();
comment.userid = data.asc_getUserId();
comment.userName = data.asc_getUserName();
comment.usercolor = (user) ? user.asc_getColor() : null;
comment.resolved = data.asc_getSolved();
comment.quote = data.asc_getQuoteText();
comment.time = date.getTime();
comment.date = dateToLocaleTimeString(date);
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;
}
}
onFilterChange (filter) {
this.storeComments.changeFilter(filter);
}
readSDKComment (id, data) {
const date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime())));
const user = this.usersStore.searchUserById(data.asc_getUserId());
const groupName = id.substr(0, id.lastIndexOf('_')+1).match(/^(doc|sheet[0-9_]+)_/);
const userName = data.asc_getUserName();
const comment = {
uid : id,
userId : data.asc_getUserId(),
userName : userName,
userColor : (user) ? user.asc_getColor() : null,
date : dateToLocaleTimeString(date),
quote : data.asc_getQuoteText(),
comment : data.asc_getText(),
resolved : data.asc_getSolved(),
unattached : !!data.asc_getDocumentFlag ? data.asc_getDocumentFlag() : false,
time : date.getTime(),
replies : [],
groupName : (groupName && groupName.length>1) ? groupName[1] : null,
userInitials : this.usersStore.getInitials(userName),
editable : this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId),
removable : this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId)
};
if (comment) {
const replies = this.readSDKReplies(data);
if (replies.length > 0) {
comment.replies = replies;
}
}
return comment;
}
readSDKReplies (data) {
const replies = [];
const repliesCount = data.asc_getRepliesCount();
let i = 0;
let date = null;
if (repliesCount) {
for (i = 0; i < repliesCount; ++i) {
date = (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())));
const 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(date),
reply : data.asc_getReply(i).asc_getText(),
time : date.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)
});
}
}
return replies;
}
render() {
return null;
}
}
class AddCommentController extends Component {
constructor(props) {
super(props);
this.getUserInfo = this.getUserInfo.bind(this);
this.onAddNewComment = this.onAddNewComment.bind(this);
}
getUserInfo () {
this.currentUser = this.props.users.currentUser;
const name = this.currentUser.asc_getUserName();
return {
name: name,
initials: this.props.users.getInitials(name),
color: this.currentUser.asc_getColor()
};
}
onAddNewComment (commentText, documentFlag) {
const api = Common.EditorApi.get();
let comment;
if (typeof Asc.asc_CCommentDataWord !== 'undefined') {
comment = new Asc.asc_CCommentDataWord(null);
} else {
comment = new Asc.asc_CCommentData(null);
}
if (commentText.length > 0) {
comment.asc_putText(commentText);
comment.asc_putTime(utcDateToString(new Date()));
comment.asc_putOnlyOfficeTime(ooDateToString(new Date()));
comment.asc_putUserId(this.currentUser.asc_getIdOriginal());
comment.asc_putUserName(this.currentUser.asc_getUserName());
comment.asc_putSolved(false);
!!comment.asc_putDocumentFlag && comment.asc_putDocumentFlag(documentFlag);
api.asc_addComment(comment);
return true;
}
return false;
}
render() {
const isOpen = this.props.storeComments.isOpenAddComment;
let userInfo;
if (isOpen) {
userInfo = this.getUserInfo();
}
return(
isOpen ? <AddComment userInfo={userInfo} onAddNewComment={this.onAddNewComment} /> : null
)
}
}
class ViewCommentsController extends Component {
constructor (props) {
super(props);
this.onCommentMenuClick = this.onCommentMenuClick.bind(this);
this.onResolveComment = this.onResolveComment.bind(this);
this.onEditComment = this.onEditComment.bind(this);
this.closeEditComment = this.closeEditComment.bind(this);
this.currentUser = this.props.users.currentUser;
this.state = {
showEditComment: false,
showEditReply: false
};
}
onChangeComment (comment) {
const ascComment = !!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null);
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
var reply = comment.replies;
if (reply && reply.length > 0) {
reply.forEach((reply) => {
var addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
onResolveComment (comment) {
let reply = null,
addReply = null,
ascComment = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(!comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
reply = comment.replies;
if (reply && reply.length > 0) {
reply.forEach((reply) => {
addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
deleteComment (comment) {
const api = Common.EditorApi.get();
comment && api.asc_removeComment(comment.uid);
}
onEditComment (comment, text) {
comment.comment = text.trim();
comment.userid = this.currentUser.asc_getIdOriginal();
comment.username = this.currentUser.asc_getUserName();
this.onChangeComment(comment);
}
deleteReply (comment, indReply) {
let replies = null,
addReply = null,
ascComment = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment && comment) {
ascComment.asc_putText(comment.comment);
ascComment.asc_putQuoteText(comment.quote);
ascComment.asc_putTime(utcDateToString(new Date(comment.time)));
ascComment.asc_putOnlyOfficeTime(ooDateToString(new Date(comment.time)));
ascComment.asc_putUserId(comment.userId);
ascComment.asc_putUserName(comment.userName);
ascComment.asc_putSolved(comment.resolved);
ascComment.asc_putGuid(comment.guid);
if (!!ascComment.asc_putDocumentFlag) {
ascComment.asc_putDocumentFlag(comment.unattached);
}
replies = comment.replies;
if (replies && replies.length) {
replies.forEach((reply) => {
if (reply.ind !== indReply) {
addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) {
addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time)));
addReply.asc_putOnlyOfficeTime(ooDateToString(new Date(reply.time)));
addReply.asc_putUserId(reply.userId);
addReply.asc_putUserName(reply.userName);
ascComment.asc_addReply(addReply);
}
}
});
}
const api = Common.EditorApi.get();
api.asc_changeComment(comment.uid, ascComment);
}
}
onCommentMenuClick (action, comment) {
const { t } = this.props;
const _t = t("Common.Collaboration", { returnObjects: true });
switch (action) {
case 'editComment':
this.setState({
showEditComment: true,
editProps: {
comment: comment,
onEditComment: this.onEditComment
}
});
console.log('editComment');
break;
case 'resolve':
this.onResolveComment(comment);
break;
case 'deleteComment':
f7.dialog.confirm(
_t.textMessageDeleteComment,
_t.textDeleteComment,
() => {
this.deleteComment(comment);
}
);
break;
case 'editReply':
this.setState({showEditReply: true});
console.log('editReply');
break;
case 'deleteReply':
f7.dialog.confirm(
_t.textMessageDeleteReply,
_t.textDeleteReply,
() => {
this.deleteReply(comment, indReply);
}
);
break;
case 'addReply':
console.log('addReply');
break;
}
}
closeEditComment () {
this.setState({showEditComment: false});
}
render() {
return(
<Fragment>
<ViewComments showEditComment={this.showEditComment}
onCommentMenuClick={this.onCommentMenuClick}
onResolveComment={this.onResolveComment}
/>
{this.state.showEditComment && <EditComment editProps={this.state.editProps} opened={this.state.showEditComment} close={this.closeEditComment}/>}
</Fragment>
)
}
}
const _CommentsController = inject('storeAppOptions', 'storeComments', 'users')(observer(CommentsController));
const _AddCommentController = inject('storeAppOptions', 'storeComments', 'users')(observer(AddCommentController));
const _ViewCommentsController = inject('storeComments', 'users')(observer(withTranslation()(ViewCommentsController)));
export {
_CommentsController as CommentsController,
_AddCommentController as AddCommentController,
_ViewCommentsController as ViewCommentsController
};