2021-02-28 17:47:47 +00:00
|
|
|
import React, {useState, useEffect, Fragment} from 'react';
|
2021-02-18 15:40:54 +00:00
|
|
|
import {observer, inject} from "mobx-react";
|
2021-03-08 18:30:42 +00:00
|
|
|
import { f7, Popup, Sheet, Popover, Page, Toolbar, Navbar, NavLeft, NavRight, NavTitle, Link, Input, Icon, List, ListItem, Actions, ActionsGroup, ActionsButton } from 'framework7-react';
|
2021-02-18 15:40:54 +00:00
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import {Device} from '../../../utils/device';
|
|
|
|
|
2021-03-10 18:08:59 +00:00
|
|
|
// Utils
|
|
|
|
const sliceQuote = (text) => {
|
|
|
|
if (text) {
|
|
|
|
let sliced = text.slice(0, 100);
|
|
|
|
if (sliced.length < text.length) {
|
|
|
|
sliced += '...';
|
|
|
|
return sliced;
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-25 16:26:42 +00:00
|
|
|
// Add comment
|
|
|
|
|
2021-02-18 15:40:54 +00:00
|
|
|
const AddCommentPopup = inject("storeComments")(observer(props => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
useEffect(() => {
|
|
|
|
f7.popup.open('.add-comment-popup');
|
2021-11-25 16:37:24 +00:00
|
|
|
if(!Device.android) f7.input.focus('.input-comment');
|
2021-02-18 15:40:54 +00:00
|
|
|
});
|
|
|
|
const userInfo = props.userInfo;
|
|
|
|
const [stateText, setText] = useState('');
|
|
|
|
return (
|
|
|
|
<Popup className="add-comment-popup">
|
|
|
|
<Navbar>
|
|
|
|
<NavLeft>
|
|
|
|
<Link onClick={() => {
|
|
|
|
f7.popup.close('.add-comment-popup');
|
2021-03-24 22:07:10 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
props.closeAddComment();
|
|
|
|
}, 500)
|
2021-02-18 15:40:54 +00:00
|
|
|
}}>{_t.textCancel}</Link>
|
|
|
|
</NavLeft>
|
|
|
|
<NavTitle>{_t.textAddComment}</NavTitle>
|
|
|
|
<NavRight>
|
|
|
|
<Link className={stateText.length === 0 && 'disabled'}
|
|
|
|
onClick={() => {
|
2021-03-26 13:23:17 +00:00
|
|
|
f7.popup.close('.add-comment-popup');
|
|
|
|
setTimeout(() => {
|
|
|
|
props.closeAddComment();
|
|
|
|
props.onAddNewComment(stateText, false)
|
|
|
|
}, 500);
|
2021-02-18 15:40:54 +00:00
|
|
|
}}>
|
|
|
|
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
|
|
|
</Link>
|
|
|
|
</NavRight>
|
|
|
|
</Navbar>
|
|
|
|
<div className='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div className="comment-header">
|
2021-02-18 15:40:54 +00:00
|
|
|
{Device.android &&
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='initials' style={{backgroundColor: `${userInfo.color}`}}>{userInfo.initials}</div>
|
2021-02-18 15:40:54 +00:00
|
|
|
}
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='name'>{userInfo.name}</div>
|
2021-02-18 15:40:54 +00:00
|
|
|
</div>
|
|
|
|
<div className='wrap-textarea'>
|
2021-12-03 13:53:09 +00:00
|
|
|
<Input className="input-comment" autofocus type='textarea' placeholder={_t.textAddComment} value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
|
2021-02-18 15:40:54 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Popup>
|
|
|
|
)
|
|
|
|
}));
|
|
|
|
|
|
|
|
const AddCommentDialog = inject("storeComments")(observer(props => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
const userInfo = props.userInfo;
|
|
|
|
const templateInitials = `<div class="initials" style="background-color: ${userInfo.color};">${userInfo.initials}</div>`;
|
|
|
|
useEffect(() => {
|
|
|
|
f7.dialog.create({
|
|
|
|
destroyOnClose: true,
|
|
|
|
containerEl: document.getElementById('add-comment-dialog'),
|
|
|
|
content:
|
|
|
|
`<div class="navbar">
|
|
|
|
<div class="navbar-bg"></div>
|
|
|
|
<div class="navbar-inner sliding">
|
|
|
|
<div class="left">
|
|
|
|
<a href="#" id="comment-cancel">${_t.textCancel}</a>
|
|
|
|
</div>
|
|
|
|
<div class="title">${_t.textAddComment}</div>
|
|
|
|
<div class="right">
|
|
|
|
<a href="#" class="done" id="comment-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div class="comment-header">
|
2021-02-18 15:40:54 +00:00
|
|
|
${Device.android ? templateInitials : ''}
|
2021-07-02 12:48:50 +00:00
|
|
|
<div class='name'>${userInfo.name}</div>
|
2021-02-18 15:40:54 +00:00
|
|
|
</div>
|
|
|
|
<div class='wrap-textarea'>
|
2021-11-25 16:37:24 +00:00
|
|
|
<textarea id='comment-text' placeholder='${_t.textAddComment}'></textarea>
|
2021-02-18 15:40:54 +00:00
|
|
|
</div>
|
|
|
|
</div>`,
|
|
|
|
on: {
|
|
|
|
opened: () => {
|
|
|
|
const cancel = document.getElementById('comment-cancel');
|
2021-11-25 16:37:24 +00:00
|
|
|
if(!Device.android) $$('#comment-text').focus();
|
2021-02-18 15:40:54 +00:00
|
|
|
cancel.addEventListener('click', () => {
|
|
|
|
f7.dialog.close();
|
2021-03-05 15:23:35 +00:00
|
|
|
props.closeAddComment();
|
2021-02-18 15:40:54 +00:00
|
|
|
});
|
|
|
|
const done = document.getElementById('comment-done');
|
|
|
|
done.addEventListener('click', () => {
|
|
|
|
const value = document.getElementById('comment-text').value;
|
2021-03-26 13:23:17 +00:00
|
|
|
if (value.length > 0) {
|
2021-02-18 15:40:54 +00:00
|
|
|
f7.dialog.close();
|
2021-03-05 15:23:35 +00:00
|
|
|
props.closeAddComment();
|
2021-03-26 13:23:17 +00:00
|
|
|
props.onAddNewComment(value, false);
|
2021-02-18 15:40:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
const area = document.getElementById('comment-text');
|
|
|
|
area.addEventListener('input', (event) => {
|
|
|
|
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
|
|
|
|
done.classList.add('disabled');
|
|
|
|
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
|
|
|
|
done.classList.remove('disabled');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
done.classList.add('disabled');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).open();
|
|
|
|
});
|
|
|
|
return (
|
2021-05-07 14:34:02 +00:00
|
|
|
<div id='add-comment-dialog' className="add-comment-dialog"></div>
|
2021-02-18 15:40:54 +00:00
|
|
|
);
|
|
|
|
}));
|
|
|
|
|
|
|
|
const AddComment = props => {
|
|
|
|
return (
|
|
|
|
Device.phone ?
|
2021-03-05 15:23:35 +00:00
|
|
|
<AddCommentPopup {...props} /> :
|
|
|
|
<AddCommentDialog {...props} />
|
2021-02-18 15:40:54 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-02-28 17:47:47 +00:00
|
|
|
// Actions
|
|
|
|
const CommentActions = ({comment, onCommentMenuClick, opened, openActionComment}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
return (
|
|
|
|
<Actions id='comment-menu' opened={opened} onActionsClosed={() => openActionComment(false)}>
|
|
|
|
<ActionsGroup>
|
|
|
|
{comment && <Fragment>
|
|
|
|
{comment.editable && <ActionsButton onClick={() => {onCommentMenuClick('editComment', comment);}}>{_t.textEdit}</ActionsButton>}
|
2021-07-06 14:13:55 +00:00
|
|
|
{!comment.resolved && comment.editable ?
|
2021-02-28 17:47:47 +00:00
|
|
|
<ActionsButton onClick={() => {onCommentMenuClick('resolve', comment);}}>{_t.textResolve}</ActionsButton> :
|
2021-07-06 14:13:55 +00:00
|
|
|
comment.editable && <ActionsButton onClick={() => {onCommentMenuClick('resolve', comment);}}>{_t.textReopen}</ActionsButton>
|
2021-02-28 17:47:47 +00:00
|
|
|
}
|
|
|
|
<ActionsButton onClick={() => {onCommentMenuClick('addReply', comment);}}>{_t.textAddReply}</ActionsButton>
|
|
|
|
{comment.removable && <ActionsButton color='red' onClick={() => {onCommentMenuClick('deleteComment', comment);}}>{_t.textDeleteComment}</ActionsButton>}
|
|
|
|
</Fragment>
|
|
|
|
}
|
|
|
|
</ActionsGroup>
|
|
|
|
<ActionsGroup>
|
|
|
|
<ActionsButton>{_t.textCancel}</ActionsButton>
|
|
|
|
</ActionsGroup>
|
|
|
|
</Actions>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-03-03 18:21:03 +00:00
|
|
|
const ReplyActions = ({comment, reply, onCommentMenuClick, opened, openActionReply}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
return (
|
|
|
|
<Actions id='reply-menu' opened={opened} onActionsClosed={() => openActionReply(false)}>
|
|
|
|
<ActionsGroup>
|
|
|
|
{reply && <Fragment>
|
|
|
|
{reply.editable && <ActionsButton onClick={() => {onCommentMenuClick('editReply', comment, reply);}}>{_t.textEdit}</ActionsButton>}
|
|
|
|
{reply.removable && <ActionsButton color='red' onClick={() => {onCommentMenuClick('deleteReply', comment, reply);}}>{_t.textDeleteReply}</ActionsButton>}
|
|
|
|
</Fragment>
|
|
|
|
}
|
|
|
|
</ActionsGroup>
|
|
|
|
<ActionsGroup>
|
|
|
|
<ActionsButton>{_t.textCancel}</ActionsButton>
|
|
|
|
</ActionsGroup>
|
|
|
|
</Actions>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-02-28 17:47:47 +00:00
|
|
|
// Edit comment
|
2021-03-03 16:49:36 +00:00
|
|
|
const EditCommentPopup = inject("storeComments")(observer(({storeComments, comment, onEditComment}) => {
|
2021-02-28 17:47:47 +00:00
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
2021-03-03 16:49:36 +00:00
|
|
|
useEffect(() => {
|
|
|
|
f7.popup.open('.edit-comment-popup');
|
|
|
|
});
|
2021-02-28 17:47:47 +00:00
|
|
|
const [stateText, setText] = useState(comment.comment);
|
|
|
|
return (
|
2021-03-03 16:49:36 +00:00
|
|
|
<Popup className="edit-comment-popup">
|
2021-02-28 17:47:47 +00:00
|
|
|
<Navbar>
|
|
|
|
<NavLeft>
|
|
|
|
<Link onClick={() => {
|
2021-03-03 16:49:36 +00:00
|
|
|
f7.popup.close('.edit-comment-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openEditComment(false);
|
|
|
|
}, 500);
|
2021-02-28 17:47:47 +00:00
|
|
|
}}>{_t.textCancel}</Link>
|
|
|
|
</NavLeft>
|
|
|
|
<NavTitle>{_t.textEditComment}</NavTitle>
|
|
|
|
<NavRight>
|
|
|
|
<Link className={stateText.length === 0 && 'disabled'}
|
|
|
|
onClick={() => {
|
2021-03-03 16:49:36 +00:00
|
|
|
f7.popup.close('.edit-comment-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openEditComment(false);
|
|
|
|
onEditComment(comment, stateText);
|
|
|
|
}, 500);
|
2021-02-28 17:47:47 +00:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
|
|
|
</Link>
|
|
|
|
</NavRight>
|
|
|
|
</Navbar>
|
|
|
|
<div className='wrap-comment'>
|
|
|
|
<div className="comment-header">
|
|
|
|
{Device.android &&
|
|
|
|
<div className='initials' style={{backgroundColor: `${comment.userColor}`}}>{comment.userInitials}</div>
|
|
|
|
}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='name'>{comment.parsedName}</div>
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='comment-date'>{comment.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='wrap-textarea'>
|
|
|
|
<Input type='textarea' placeholder={_t.textEditComment} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Popup>
|
|
|
|
)
|
2021-03-03 16:49:36 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
const EditCommentDialog = inject("storeComments")(observer(({storeComments, comment, onEditComment}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
const templateInitials = `<div class="initials" style="background-color: ${comment.userColor};">${comment.userInitials}</div>`;
|
|
|
|
useEffect(() => {
|
|
|
|
f7.dialog.create({
|
|
|
|
destroyOnClose: true,
|
|
|
|
containerEl: document.getElementById('edit-comment-dialog'),
|
|
|
|
content:
|
|
|
|
`<div class="navbar">
|
|
|
|
<div class="navbar-bg"></div>
|
|
|
|
<div class="navbar-inner sliding">
|
|
|
|
<div class="left">
|
|
|
|
<a href="#" id="comment-cancel">${_t.textCancel}</a>
|
|
|
|
</div>
|
|
|
|
<div class="title">${_t.textEditComment}</div>
|
|
|
|
<div class="right">
|
|
|
|
<a href="#" class="done" id="comment-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div class="comment-header">
|
2021-03-03 16:49:36 +00:00
|
|
|
${Device.android ? templateInitials : ''}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div class='name'>${comment.parsedName}</div>
|
2021-03-03 16:49:36 +00:00
|
|
|
<div class='comment-date'>${comment.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-textarea'>
|
|
|
|
<textarea id='comment-text' placeholder='${_t.textEditComment}' autofocus>${comment.comment}</textarea>
|
|
|
|
</div>
|
|
|
|
</div>`,
|
|
|
|
on: {
|
|
|
|
opened: () => {
|
|
|
|
const cancel = document.getElementById('comment-cancel');
|
|
|
|
cancel.addEventListener('click', () => {
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openEditComment(false);
|
|
|
|
});
|
|
|
|
const done = document.getElementById('comment-done');
|
|
|
|
done.addEventListener('click', () => {
|
|
|
|
const value = document.getElementById('comment-text').value;
|
|
|
|
if (value.length > 0) {
|
|
|
|
onEditComment(comment, value);
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openEditComment(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const area = document.getElementById('comment-text');
|
|
|
|
area.addEventListener('input', (event) => {
|
|
|
|
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
|
|
|
|
done.classList.add('disabled');
|
|
|
|
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
|
|
|
|
done.classList.remove('disabled');
|
|
|
|
}
|
|
|
|
});
|
2021-04-27 12:28:25 +00:00
|
|
|
},
|
|
|
|
open: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
|
|
|
|
},
|
|
|
|
closed: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
|
2021-03-03 16:49:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}).open();
|
|
|
|
});
|
|
|
|
return (
|
2021-05-07 14:34:02 +00:00
|
|
|
<div id='edit-comment-dialog' className="edit-comment-dialog"></div>
|
2021-03-03 16:49:36 +00:00
|
|
|
);
|
|
|
|
}));
|
|
|
|
|
|
|
|
const EditComment = ({comment, onEditComment}) => {
|
|
|
|
return (
|
|
|
|
Device.phone ?
|
|
|
|
<EditCommentPopup comment={comment} onEditComment={onEditComment}/> :
|
|
|
|
<EditCommentDialog comment={comment} onEditComment={onEditComment}/>
|
|
|
|
)
|
2021-02-28 17:47:47 +00:00
|
|
|
};
|
|
|
|
|
2021-03-03 16:49:36 +00:00
|
|
|
const AddReplyPopup = inject("storeComments")(observer(({storeComments, userInfo, comment, onAddReply}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
useEffect(() => {
|
|
|
|
f7.popup.open('.add-reply-popup');
|
|
|
|
});
|
|
|
|
const [stateText, setText] = useState('');
|
|
|
|
return (
|
|
|
|
<Popup className="add-reply-popup">
|
|
|
|
<Navbar>
|
|
|
|
<NavLeft>
|
|
|
|
<Link onClick={() => {
|
|
|
|
f7.popup.close('.add-reply-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openAddReply(false);
|
|
|
|
}, 500);
|
2021-03-03 16:49:36 +00:00
|
|
|
}}>{_t.textCancel}</Link>
|
|
|
|
</NavLeft>
|
|
|
|
<NavTitle>{_t.textAddReply}</NavTitle>
|
|
|
|
<NavRight>
|
|
|
|
<Link className={stateText.length === 0 && 'disabled'}
|
|
|
|
onClick={() => {
|
|
|
|
f7.popup.close('.add-reply-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openAddReply(false);
|
|
|
|
onAddReply(comment, stateText);
|
|
|
|
}, 500);
|
2021-03-03 16:49:36 +00:00
|
|
|
}}>
|
|
|
|
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
|
|
|
</Link>
|
|
|
|
</NavRight>
|
|
|
|
</Navbar>
|
|
|
|
<div className='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div className="comment-header">
|
2021-03-03 16:49:36 +00:00
|
|
|
{Device.android &&
|
|
|
|
<div className='initials' style={{backgroundColor: `${userInfo.color}`}}>{userInfo.initials}</div>
|
|
|
|
}
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='name'>{userInfo.name}</div>
|
2021-03-03 16:49:36 +00:00
|
|
|
</div>
|
|
|
|
<div className='wrap-textarea'>
|
|
|
|
<Input type='textarea' placeholder={_t.textAddReply} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Popup>
|
|
|
|
)
|
|
|
|
}));
|
|
|
|
|
|
|
|
const AddReplyDialog = inject("storeComments")(observer(({storeComments, userInfo, comment, onAddReply}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
const templateInitials = `<div class="initials" style="background-color: ${userInfo.color};">${userInfo.initials}</div>`;
|
|
|
|
useEffect(() => {
|
|
|
|
f7.dialog.create({
|
|
|
|
destroyOnClose: true,
|
|
|
|
containerEl: document.getElementById('add-reply-dialog'),
|
|
|
|
content:
|
|
|
|
`<div class="navbar">
|
|
|
|
<div class="navbar-bg"></div>
|
|
|
|
<div class="navbar-inner sliding">
|
|
|
|
<div class="left">
|
|
|
|
<a href="#" id="reply-cancel">${_t.textCancel}</a>
|
|
|
|
</div>
|
|
|
|
<div class="title">${_t.textAddReply}</div>
|
|
|
|
<div class="right">
|
|
|
|
<a href="#" class="done" id="reply-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div class="comment-header">
|
2021-03-03 16:49:36 +00:00
|
|
|
${Device.android ? templateInitials : ''}
|
2021-07-02 12:48:50 +00:00
|
|
|
<div class='name'>${userInfo.name}</div>
|
2021-03-03 16:49:36 +00:00
|
|
|
</div>
|
|
|
|
<div class='wrap-textarea'>
|
|
|
|
<textarea id='reply-text' placeholder='${_t.textAddReply}' autofocus></textarea>
|
|
|
|
</div>
|
|
|
|
</div>`,
|
|
|
|
on: {
|
|
|
|
opened: () => {
|
|
|
|
const cancel = document.getElementById('reply-cancel');
|
|
|
|
cancel.addEventListener('click', () => {
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openAddReply(false);
|
|
|
|
});
|
|
|
|
const done = document.getElementById('reply-done');
|
|
|
|
done.addEventListener('click', () => {
|
|
|
|
const value = document.getElementById('reply-text').value;
|
|
|
|
if (value.length > 0) {
|
|
|
|
onAddReply(comment, value);
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openAddReply(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const area = document.getElementById('reply-text');
|
|
|
|
area.addEventListener('input', (event) => {
|
|
|
|
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
|
|
|
|
done.classList.add('disabled');
|
|
|
|
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
|
|
|
|
done.classList.remove('disabled');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
done.classList.add('disabled');
|
2021-04-27 12:28:25 +00:00
|
|
|
},
|
|
|
|
open: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
|
|
|
|
},
|
|
|
|
closed: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
|
2021-03-03 16:49:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}).open();
|
|
|
|
});
|
|
|
|
return (
|
2021-05-07 14:34:02 +00:00
|
|
|
<div id='add-reply-dialog' className="add-reply-dialog"></div>
|
2021-03-03 16:49:36 +00:00
|
|
|
);
|
|
|
|
}));
|
|
|
|
|
|
|
|
const AddReply = ({userInfo, comment, onAddReply}) => {
|
2021-02-28 17:47:47 +00:00
|
|
|
return (
|
|
|
|
Device.phone ?
|
2021-03-03 16:49:36 +00:00
|
|
|
<AddReplyPopup userInfo={userInfo} comment={comment} onAddReply={onAddReply}/> :
|
|
|
|
<AddReplyDialog userInfo={userInfo} comment={comment} onAddReply={onAddReply}/>
|
2021-02-28 17:47:47 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-03-03 18:21:03 +00:00
|
|
|
const EditReplyPopup = inject("storeComments")(observer(({storeComments, comment, reply, onEditReply}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
useEffect(() => {
|
|
|
|
f7.popup.open('.edit-reply-popup');
|
|
|
|
});
|
|
|
|
const [stateText, setText] = useState(reply.reply);
|
|
|
|
return (
|
|
|
|
<Popup className="edit-reply-popup">
|
|
|
|
<Navbar>
|
|
|
|
<NavLeft>
|
|
|
|
<Link onClick={() => {
|
|
|
|
f7.popup.close('.edit-reply-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openEditReply(false);
|
|
|
|
}, 500);
|
2021-03-03 18:21:03 +00:00
|
|
|
}}>{_t.textCancel}</Link>
|
|
|
|
</NavLeft>
|
|
|
|
<NavTitle>{_t.textEditReply}</NavTitle>
|
|
|
|
<NavRight>
|
|
|
|
<Link className={stateText.length === 0 && 'disabled'}
|
|
|
|
onClick={() => {
|
|
|
|
f7.popup.close('.edit-reply-popup');
|
2021-03-26 13:23:17 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
storeComments.openEditReply(false);
|
|
|
|
onEditReply(comment, reply, stateText);
|
|
|
|
}, 500);
|
2021-03-03 18:21:03 +00:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{Device.android ? <Icon icon='icon-done-comment-white'/> : _t.textDone}
|
|
|
|
</Link>
|
|
|
|
</NavRight>
|
|
|
|
</Navbar>
|
|
|
|
<div className='wrap-comment'>
|
|
|
|
<div className="comment-header">
|
|
|
|
{Device.android &&
|
|
|
|
<div className='initials' style={{backgroundColor: `${reply.userColor}`}}>{reply.userInitials}</div>
|
|
|
|
}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='name'>{reply.parsedName}</div>
|
2021-03-03 18:21:03 +00:00
|
|
|
<div className='reply-date'>{reply.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='wrap-textarea'>
|
|
|
|
<Input type='textarea' placeholder={_t.textEditReply} autofocus value={stateText} onChange={(event) => {setText(event.target.value);}}></Input>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Popup>
|
|
|
|
)
|
|
|
|
}));
|
|
|
|
|
|
|
|
const EditReplyDialog = inject("storeComments")(observer(({storeComments, comment, reply, onEditReply}) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
|
|
|
const templateInitials = `<div class="initials" style="background-color: ${reply.userColor};">${reply.userInitials}</div>`;
|
|
|
|
useEffect(() => {
|
|
|
|
f7.dialog.create({
|
|
|
|
destroyOnClose: true,
|
|
|
|
containerEl: document.getElementById('edit-reply-dialog'),
|
|
|
|
content:
|
|
|
|
`<div class="navbar">
|
|
|
|
<div class="navbar-bg"></div>
|
|
|
|
<div class="navbar-inner sliding">
|
|
|
|
<div class="left">
|
|
|
|
<a href="#" id="reply-cancel">${_t.textCancel}</a>
|
|
|
|
</div>
|
|
|
|
<div class="title">${_t.textEditReply}</div>
|
|
|
|
<div class="right">
|
|
|
|
<a href="#" class="done" id="reply-done">${ Device.android ? '<i class="icon icon-done-comment-white"></i>' : _t.textDone}</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-comment'>
|
2021-03-04 17:25:50 +00:00
|
|
|
<div class="comment-header">
|
2021-03-03 18:21:03 +00:00
|
|
|
${Device.android ? templateInitials : ''}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div class='name'>${reply.parsedName}</div>
|
2021-03-03 18:21:03 +00:00
|
|
|
<div class='reply-date'>${reply.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class='wrap-textarea'>
|
|
|
|
<textarea id='reply-text' placeholder='${_t.textEditComment}' autofocus>${reply.reply}</textarea>
|
|
|
|
</div>
|
|
|
|
</div>`,
|
|
|
|
on: {
|
|
|
|
opened: () => {
|
|
|
|
const cancel = document.getElementById('reply-cancel');
|
|
|
|
cancel.addEventListener('click', () => {
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openEditReply(false);
|
|
|
|
});
|
|
|
|
const done = document.getElementById('reply-done');
|
|
|
|
done.addEventListener('click', () => {
|
|
|
|
const value = document.getElementById('reply-text').value;
|
|
|
|
if (value.length > 0) {
|
|
|
|
onEditReply(comment, reply, value);
|
|
|
|
f7.dialog.close();
|
|
|
|
storeComments.openEditReply(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const area = document.getElementById('reply-text');
|
|
|
|
area.addEventListener('input', (event) => {
|
|
|
|
if (event.target.value.length === 0 && !done.classList.contains('disabled')) {
|
|
|
|
done.classList.add('disabled');
|
|
|
|
} else if (event.target.value.length > 0 && done.classList.contains('disabled')) {
|
|
|
|
done.classList.remove('disabled');
|
|
|
|
}
|
|
|
|
});
|
2021-04-27 12:28:25 +00:00
|
|
|
},
|
|
|
|
open: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.add('over-popover');
|
|
|
|
},
|
|
|
|
closed: () => {
|
|
|
|
$$('.dialog-backdrop.backdrop-in')[0].classList.remove('over-popover');
|
2021-03-03 18:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}).open();
|
|
|
|
});
|
|
|
|
return (
|
2021-05-07 14:34:02 +00:00
|
|
|
<div id='edit-reply-dialog' className="edit-reply-dialog"></div>
|
2021-03-03 18:21:03 +00:00
|
|
|
);
|
|
|
|
}));
|
|
|
|
|
|
|
|
const EditReply = ({comment, reply, onEditReply}) => {
|
|
|
|
return (
|
|
|
|
Device.phone ?
|
|
|
|
<EditReplyPopup comment={comment} reply={reply} onEditReply={onEditReply}/> :
|
|
|
|
<EditReplyDialog comment={comment} reply={reply} onEditReply={onEditReply}/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-05-24 13:41:31 +00:00
|
|
|
const pickLink = (message) => {
|
|
|
|
let arrayComment = [], offset, len;
|
|
|
|
message.replace(Common.Utils.ipStrongRe, function(subStr) {
|
|
|
|
let result = /[\.,\?\+;:=!\(\)]+$/.exec(subStr);
|
|
|
|
if (result)
|
|
|
|
subStr = subStr.substring(0, result.index);
|
|
|
|
offset = arguments[arguments.length-2];
|
2021-07-09 16:04:06 +00:00
|
|
|
arrayComment.push({start: offset, end: subStr.length+offset, str: <a onClick={() => window.open(subStr)} href={subStr} target="_blank" data-can-copy="true">{subStr}</a>});
|
2021-05-24 13:41:31 +00:00
|
|
|
return '';
|
|
|
|
});
|
|
|
|
|
|
|
|
if (message.length<1000 || message.search(/\S{255,}/)<0)
|
2021-07-08 18:18:15 +00:00
|
|
|
message.replace(Common.Utils.hostnameStrongRe, function(subStr) {
|
|
|
|
let result = /[\.,\?\+;:=!\(\)]+$/.exec(subStr);
|
|
|
|
if (result)
|
|
|
|
subStr = subStr.substring(0, result.index);
|
|
|
|
let ref = (! /(((^https?)|(^ftp)):\/\/)/i.test(subStr) ) ? ('http://' + subStr) : subStr;
|
|
|
|
offset = arguments[arguments.length-2];
|
|
|
|
len = subStr.length;
|
|
|
|
let elem = arrayComment.find(function(item){
|
|
|
|
return ( (offset>=item.start) && (offset<item.end) ||
|
|
|
|
(offset<=item.start) && (offset+len>item.start));
|
2021-05-24 13:41:31 +00:00
|
|
|
});
|
2021-07-08 18:18:15 +00:00
|
|
|
if (!elem)
|
2021-07-09 16:04:06 +00:00
|
|
|
arrayComment.push({start: offset, end: len+offset, str: <a onClick={() => window.open(ref)} href={ref} target="_blank" data-can-copy="true">{subStr}</a>});
|
2021-07-08 18:18:15 +00:00
|
|
|
return '';
|
|
|
|
});
|
2021-05-24 13:41:31 +00:00
|
|
|
|
2021-07-08 18:18:15 +00:00
|
|
|
message.replace(Common.Utils.emailStrongRe, function(subStr) {
|
|
|
|
let ref = (! /((^mailto:)\/\/)/i.test(subStr) ) ? ('mailto:' + subStr) : subStr;
|
|
|
|
offset = arguments[arguments.length-2];
|
|
|
|
len = subStr.length;
|
|
|
|
let elem = arrayComment.find(function(item){
|
|
|
|
return ( (offset>=item.start) && (offset<item.end) ||
|
|
|
|
(offset<=item.start) && (offset+len>item.start));
|
|
|
|
});
|
|
|
|
if (!elem)
|
2021-07-09 16:04:06 +00:00
|
|
|
arrayComment.push({start: offset, end: len+offset, str: <a onClick={() => window.open(ref)} href={ref}>{subStr}</a>});
|
2021-07-08 18:18:15 +00:00
|
|
|
return '';
|
|
|
|
});
|
2021-05-24 13:41:31 +00:00
|
|
|
|
2021-07-08 18:18:15 +00:00
|
|
|
arrayComment = arrayComment.sort(function(item1,item2){ return item1.start - item2.start; });
|
|
|
|
|
2022-05-12 17:23:02 +00:00
|
|
|
let str_res = (arrayComment.length>0) ? <label>{message.substring(0, arrayComment[0].start)}{arrayComment[0].str}</label> : <label>{message}</label>;
|
2021-07-08 18:18:15 +00:00
|
|
|
|
|
|
|
for (var i=1; i<arrayComment.length; i++) {
|
2021-07-09 16:04:06 +00:00
|
|
|
str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, arrayComment[i].start))}{arrayComment[i].str}</label>;
|
2021-07-08 18:18:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (arrayComment.length>0) {
|
2021-07-09 16:04:06 +00:00
|
|
|
str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, message.length))}</label>;
|
2021-07-08 18:18:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return str_res;
|
2021-05-24 13:41:31 +00:00
|
|
|
}
|
|
|
|
|
2021-02-25 16:26:42 +00:00
|
|
|
// View comments
|
2021-10-22 11:11:14 +00:00
|
|
|
|
2021-10-20 17:24:08 +00:00
|
|
|
const ViewComments = inject("storeComments", "storeAppOptions", "storeReview")(observer(({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment, showComment, storeReview, wsProps}) => {
|
2021-02-25 16:26:42 +00:00
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
2021-02-28 17:47:47 +00:00
|
|
|
const isAndroid = Device.android;
|
2021-08-03 15:14:45 +00:00
|
|
|
const displayMode = storeReview.displayMode;
|
2021-02-25 16:26:42 +00:00
|
|
|
|
2021-02-28 17:47:47 +00:00
|
|
|
const viewMode = !storeAppOptions.canComments;
|
2021-03-26 13:23:17 +00:00
|
|
|
const comments = storeComments.groupCollectionFilter || storeComments.collectionComments;
|
2022-04-19 12:54:18 +00:00
|
|
|
const isEdit = storeAppOptions.isEdit || storeAppOptions.isRestrictedEdit;
|
2021-07-07 15:31:44 +00:00
|
|
|
const sortComments = comments.length > 0 ? [...comments].sort((a, b) => a.time > b.time ? -1 : 1) : null;
|
2021-02-28 17:47:47 +00:00
|
|
|
|
2021-03-03 18:21:03 +00:00
|
|
|
const [clickComment, setComment] = useState();
|
2021-02-28 17:47:47 +00:00
|
|
|
const [commentActionsOpened, openActionComment] = useState(false);
|
|
|
|
|
2021-03-03 18:21:03 +00:00
|
|
|
const [reply, setReply] = useState();
|
|
|
|
const [replyActionsOpened, openActionReply] = useState(false);
|
|
|
|
|
2021-02-25 16:26:42 +00:00
|
|
|
return (
|
|
|
|
<Page>
|
2021-05-17 13:14:41 +00:00
|
|
|
<Navbar title={_t.textComments} backLink={_t.textBack}>
|
|
|
|
{Device.phone &&
|
|
|
|
<NavRight>
|
|
|
|
<Link sheetClose=".coauth__sheet">
|
|
|
|
<Icon icon='icon-expand-down'/>
|
|
|
|
</Link>
|
|
|
|
</NavRight>
|
|
|
|
}
|
|
|
|
</Navbar>
|
2021-03-26 13:23:17 +00:00
|
|
|
{!sortComments ?
|
2021-02-25 16:26:42 +00:00
|
|
|
<div className='no-comments'>{_t.textNoComments}</div> :
|
|
|
|
<List className='comment-list'>
|
2021-03-26 13:23:17 +00:00
|
|
|
{sortComments.map((comment, indexComment) => {
|
2021-02-25 16:26:42 +00:00
|
|
|
return (
|
2021-07-06 14:13:55 +00:00
|
|
|
!comment.hide &&
|
2021-05-31 15:08:02 +00:00
|
|
|
<ListItem key={`comment-${indexComment}`} onClick={e => {
|
|
|
|
!e.target.closest('.comment-menu') && !e.target.closest('.reply-menu') ? showComment(comment) : null}}>
|
2021-02-28 17:47:47 +00:00
|
|
|
<div slot='header' className='comment-header'>
|
|
|
|
<div className='left'>
|
|
|
|
{isAndroid && <div className='initials' style={{backgroundColor: `${comment.userColor ? comment.userColor : '#cfcfcf'}`}}>{comment.userInitials}</div>}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='user-name'>{comment.parsedName}</div>
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='comment-date'>{comment.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-02-16 08:05:41 +00:00
|
|
|
{isEdit && !viewMode &&
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='right'>
|
2021-10-21 19:45:19 +00:00
|
|
|
{(comment.editable && displayMode === 'markup' && !wsProps?.Objects) && <div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'} /></div> }
|
|
|
|
{(displayMode === 'markup' && !wsProps?.Objects) &&
|
2021-08-03 15:14:45 +00:00
|
|
|
<div className='comment-menu'
|
|
|
|
onClick={() => {setComment(comment); openActionComment(true);}}>
|
|
|
|
<Icon icon='icon-menu-comment'/>
|
|
|
|
</div>
|
|
|
|
}
|
2021-02-28 17:47:47 +00:00
|
|
|
</div>
|
|
|
|
}
|
2021-02-25 16:26:42 +00:00
|
|
|
</div>
|
|
|
|
<div slot='footer'>
|
2021-02-28 17:47:47 +00:00
|
|
|
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
|
2021-05-25 13:46:24 +00:00
|
|
|
<div className='comment-text'><pre>{pickLink(comment.comment)}</pre></div>
|
2021-02-25 16:26:42 +00:00
|
|
|
{comment.replies.length > 0 &&
|
2021-03-04 17:25:50 +00:00
|
|
|
<ul className='reply-list'>
|
2021-02-25 16:26:42 +00:00
|
|
|
{comment.replies.map((reply, indexReply) => {
|
|
|
|
return (
|
|
|
|
<li key={`reply-${indexComment}-${indexReply}`}
|
|
|
|
className='reply-item'
|
|
|
|
>
|
|
|
|
<div className='item-content'>
|
|
|
|
<div className='item-inner'>
|
|
|
|
<div className='item-title'>
|
2021-02-28 17:47:47 +00:00
|
|
|
<div slot='header' className='reply-header'>
|
|
|
|
<div className='left'>
|
|
|
|
{isAndroid && <div className='initials' style={{backgroundColor: `${reply.userColor ? reply.userColor : '#cfcfcf'}`}}>{reply.userInitials}</div>}
|
|
|
|
<div>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='user-name'>{reply.parsedName}</div>
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='reply-date'>{reply.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-02-16 08:05:41 +00:00
|
|
|
{isEdit && !viewMode && reply.editable &&
|
2021-02-28 17:47:47 +00:00
|
|
|
<div className='right'>
|
2021-03-03 18:21:03 +00:00
|
|
|
<div className='reply-menu'
|
|
|
|
onClick={() => {setComment(comment); setReply(reply); openActionReply(true);}}
|
|
|
|
>
|
|
|
|
<Icon icon='icon-menu-comment'/>
|
|
|
|
</div>
|
2021-02-28 17:47:47 +00:00
|
|
|
</div>
|
|
|
|
}
|
2021-02-25 16:26:42 +00:00
|
|
|
</div>
|
|
|
|
<div slot='footer'>
|
2021-05-25 09:07:02 +00:00
|
|
|
<div className='reply-text'><pre>{pickLink(reply.reply)}</pre></div>
|
2021-02-25 16:26:42 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</ul>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</ListItem>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
</List>
|
|
|
|
}
|
|
|
|
|
2021-02-28 17:47:47 +00:00
|
|
|
<CommentActions comment={clickComment} onCommentMenuClick={onCommentMenuClick} opened={commentActionsOpened} openActionComment={openActionComment}/>
|
2021-03-03 18:21:03 +00:00
|
|
|
<ReplyActions comment={clickComment} reply={reply} onCommentMenuClick={onCommentMenuClick} opened={replyActionsOpened} openActionReply={openActionReply}/>
|
2021-02-25 16:26:42 +00:00
|
|
|
</Page>
|
|
|
|
)
|
2021-10-20 17:24:08 +00:00
|
|
|
}));
|
2021-02-25 16:26:42 +00:00
|
|
|
|
2021-10-21 19:45:19 +00:00
|
|
|
const CommentList = inject("storeComments", "storeAppOptions", "storeReview")(observer(({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment, storeReview, wsProps}) => {
|
2021-03-08 18:30:42 +00:00
|
|
|
const { t } = useTranslation();
|
|
|
|
const _t = t('Common.Collaboration', {returnObjects: true});
|
2021-03-10 18:08:59 +00:00
|
|
|
const isAndroid = Device.android;
|
2021-08-03 15:14:45 +00:00
|
|
|
const displayMode = storeReview.displayMode;
|
2021-03-10 18:08:59 +00:00
|
|
|
|
|
|
|
const viewMode = !storeAppOptions.canComments;
|
2022-04-19 12:54:18 +00:00
|
|
|
const isEdit = storeAppOptions.isEdit || storeAppOptions.isRestrictedEdit;
|
2021-03-10 18:08:59 +00:00
|
|
|
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);
|
|
|
|
|
2021-03-11 20:38:53 +00:00
|
|
|
const onViewPrevComment = () => {
|
|
|
|
if (currentIndex - 1 < 0) {
|
|
|
|
setCurrentIndex(comments.length - 1);
|
|
|
|
} else {
|
|
|
|
setCurrentIndex(currentIndex - 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const onViewNextComment = () => {
|
2021-06-09 14:17:42 +00:00
|
|
|
if (currentIndex + 1 >= comments.length) {
|
2021-03-11 20:38:53 +00:00
|
|
|
setCurrentIndex(0);
|
|
|
|
} else {
|
|
|
|
setCurrentIndex(currentIndex + 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-06-08 13:59:11 +00:00
|
|
|
if(!comment) {
|
2021-06-09 14:17:42 +00:00
|
|
|
if (comments.length > 0) {
|
|
|
|
onViewNextComment();
|
|
|
|
}
|
2021-06-08 13:59:11 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-03-10 18:08:59 +00:00
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
<Toolbar position='bottom'>
|
2022-02-16 08:05:41 +00:00
|
|
|
{isEdit && !viewMode &&
|
2021-10-21 19:45:19 +00:00
|
|
|
<Link className={`btn-add-reply${wsProps?.Objects ? ' disabled' : ''}`} href='#' onClick={() => {onCommentMenuClick('addReply', comment);}}>{_t.textAddReply}</Link>
|
2021-03-11 20:38:53 +00:00
|
|
|
}
|
2021-03-10 18:08:59 +00:00
|
|
|
<div className='comment-navigation row'>
|
2021-03-11 20:38:53 +00:00
|
|
|
<Link href='#' onClick={onViewPrevComment}><Icon slot='media' icon='icon-prev'/></Link>
|
|
|
|
<Link href='#' onClick={onViewNextComment}><Icon slot='media' icon='icon-next'/></Link>
|
2021-03-10 18:08:59 +00:00
|
|
|
</div>
|
|
|
|
</Toolbar>
|
2021-05-17 16:51:12 +00:00
|
|
|
<div className='pages'>
|
2021-06-08 13:59:11 +00:00
|
|
|
<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>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='user-name'>{comment.parsedName}</div>
|
2021-06-08 13:59:11 +00:00
|
|
|
<div className='comment-date'>{comment.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-02-16 08:05:41 +00:00
|
|
|
{isEdit && !viewMode &&
|
2021-06-08 13:59:11 +00:00
|
|
|
<div className='right'>
|
2021-10-21 19:45:19 +00:00
|
|
|
{(comment.editable && displayMode === 'markup' && !wsProps?.Objects) && <div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'}/></div>}
|
|
|
|
{(displayMode === 'markup' && !wsProps?.Objects) &&
|
2021-08-03 15:14:45 +00:00
|
|
|
<div className='comment-menu'
|
|
|
|
onClick={() => {openActionComment(true);}}>
|
|
|
|
<Icon icon='icon-menu-comment'/>
|
|
|
|
</div>
|
|
|
|
}
|
2021-06-08 13:59:11 +00:00
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
<div slot='footer'>
|
|
|
|
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
|
|
|
|
<div className='comment-text'><pre>{pickLink(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>
|
2021-07-02 12:48:50 +00:00
|
|
|
<div className='user-name'>{reply.parsedName}</div>
|
2021-06-08 13:59:11 +00:00
|
|
|
<div className='reply-date'>{reply.date}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-02-16 08:05:41 +00:00
|
|
|
{isEdit && !viewMode && reply.editable &&
|
2021-06-08 13:59:11 +00:00
|
|
|
<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>{pickLink(reply.reply)}</pre></div>
|
|
|
|
</div>
|
2021-03-10 18:08:59 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2021-06-08 13:59:11 +00:00
|
|
|
</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>
|
2021-05-17 16:51:12 +00:00
|
|
|
</div>
|
2021-03-10 18:08:59 +00:00
|
|
|
</Fragment>
|
|
|
|
)
|
2021-06-08 13:59:11 +00:00
|
|
|
|
2021-03-10 18:08:59 +00:00
|
|
|
}));
|
2021-03-08 18:30:42 +00:00
|
|
|
|
2021-10-21 19:45:19 +00:00
|
|
|
const ViewCommentSheet = ({closeCurComments, onCommentMenuClick, onResolveComment, wsProps}) => {
|
2021-03-08 18:30:42 +00:00
|
|
|
useEffect(() => {
|
|
|
|
f7.sheet.open('#view-comment-sheet');
|
|
|
|
});
|
2021-03-09 16:29:06 +00:00
|
|
|
|
|
|
|
const [stateHeight, setHeight] = useState('45%');
|
|
|
|
const [stateOpacity, setOpacity] = useState(1);
|
|
|
|
|
|
|
|
const [stateStartY, setStartY] = useState();
|
|
|
|
const [isNeedClose, setNeedClose] = useState(false);
|
|
|
|
|
2021-03-08 18:30:42 +00:00
|
|
|
const handleTouchStart = (event) => {
|
|
|
|
const touchObj = event.changedTouches[0];
|
2021-03-09 16:29:06 +00:00
|
|
|
setStartY(parseInt(touchObj.clientY));
|
2021-03-08 18:30:42 +00:00
|
|
|
};
|
|
|
|
const handleTouchMove = (event) => {
|
|
|
|
const touchObj = event.changedTouches[0];
|
2021-03-09 16:29:06 +00:00
|
|
|
const dist = parseInt(touchObj.clientY) - stateStartY;
|
|
|
|
if (dist < 0) { // to top
|
|
|
|
setHeight('90%');
|
|
|
|
setOpacity(1);
|
|
|
|
setNeedClose(false);
|
|
|
|
} else if (dist < 80) {
|
|
|
|
setHeight('45%');
|
|
|
|
setOpacity(1);
|
|
|
|
setNeedClose(false);
|
2021-03-08 18:30:42 +00:00
|
|
|
} else {
|
2021-03-09 16:29:06 +00:00
|
|
|
setNeedClose(true);
|
|
|
|
setOpacity(0.6);
|
2021-03-08 18:30:42 +00:00
|
|
|
}
|
|
|
|
};
|
2021-03-09 16:29:06 +00:00
|
|
|
const handleTouchEnd = (event) => {
|
|
|
|
const touchObj = event.changedTouches[0];
|
|
|
|
const swipeEnd = parseInt(touchObj.clientY);
|
|
|
|
const dist = swipeEnd - stateStartY;
|
|
|
|
if (isNeedClose) {
|
|
|
|
closeCurComments();
|
|
|
|
} else if (stateHeight === '90%' && dist > 20) {
|
|
|
|
setHeight('45%');
|
2021-03-08 18:30:42 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
return (
|
2021-03-09 16:29:06 +00:00
|
|
|
<Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}>
|
|
|
|
<div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
|
2021-03-08 18:30:42 +00:00
|
|
|
<Icon icon='icon-swipe'/>
|
|
|
|
</div>
|
2021-10-21 19:45:19 +00:00
|
|
|
<CommentList wsProps={wsProps} onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment}/>
|
2021-03-08 18:30:42 +00:00
|
|
|
</Sheet>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-10-21 19:45:19 +00:00
|
|
|
const ViewCommentPopover = ({onCommentMenuClick, onResolveComment, wsProps}) => {
|
2021-03-08 18:30:42 +00:00
|
|
|
useEffect(() => {
|
|
|
|
f7.popover.open('#view-comment-popover', '#btn-coauth');
|
|
|
|
});
|
2021-10-20 17:24:08 +00:00
|
|
|
|
2021-03-08 18:30:42 +00:00
|
|
|
return (
|
2021-04-27 12:28:25 +00:00
|
|
|
<Popover id='view-comment-popover' style={{height: '410px'}} closeByOutsideClick={false}>
|
2021-10-21 19:45:19 +00:00
|
|
|
<CommentList wsProps={wsProps} onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment} />
|
2021-03-08 18:30:42 +00:00
|
|
|
</Popover>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
const ViewCurrentComments = props => {
|
|
|
|
return (
|
|
|
|
Device.phone ?
|
|
|
|
<ViewCommentSheet {...props}/> :
|
|
|
|
<ViewCommentPopover {...props}/>
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-02-25 16:26:42 +00:00
|
|
|
export {
|
|
|
|
AddComment,
|
2021-02-28 17:47:47 +00:00
|
|
|
EditComment,
|
2021-03-03 16:49:36 +00:00
|
|
|
AddReply,
|
2021-03-03 18:21:03 +00:00
|
|
|
EditReply,
|
2021-10-20 17:24:08 +00:00
|
|
|
ViewComments,
|
2021-10-21 19:45:19 +00:00
|
|
|
ViewCurrentComments
|
2021-03-08 18:30:42 +00:00
|
|
|
};
|