mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-30 01:05:18 +02:00
[DEV-162] Fix ticket comment issues (#1081)
* Fix bug in UI * Fix bug in backend * Fix some issues * Improve coding * Improve coding
This commit is contained in:
parent
f5e9b2602c
commit
402af565a9
@ -31,7 +31,9 @@ class TicketEvent extends React.Component {
|
||||
private: React.PropTypes.string,
|
||||
edited: React.PropTypes.bool,
|
||||
edit: React.PropTypes.bool,
|
||||
onToggleEdit: React.PropTypes.func
|
||||
onToggleEdit: React.PropTypes.func,
|
||||
isLastComment: React.PropTypes.bool,
|
||||
isTicketClosed: React.PropTypes.bool
|
||||
};
|
||||
|
||||
state = {
|
||||
@ -92,12 +94,7 @@ class TicketEvent extends React.Component {
|
||||
}
|
||||
|
||||
renderComment() {
|
||||
const {
|
||||
author,
|
||||
date,
|
||||
edit,
|
||||
file
|
||||
} = this.props;
|
||||
const { author, date, edit, file } = this.props;
|
||||
const customFields = (author && author.customfields) || [];
|
||||
|
||||
return (
|
||||
@ -142,10 +139,13 @@ class TicketEvent extends React.Component {
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
const { content, author, userId, userStaff, isLastComment, isTicketClosed } = this.props;
|
||||
const { id, staff } = author;
|
||||
|
||||
return (
|
||||
<div className="ticket-event__comment-content ql-editor">
|
||||
<div dangerouslySetInnerHTML={{__html: this.props.content}}></div>
|
||||
{((this.props.author.id == this.props.userId && this.props.author.staff == this.props.userStaff) || this.props.userStaff) ? this.renderEditIcon() : null}
|
||||
<div dangerouslySetInnerHTML={{__html: content}}></div>
|
||||
{(id == userId && staff == userStaff && isLastComment && !isTicketClosed) ? this.renderEditIcon() : null }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -83,30 +83,46 @@ class TicketViewer extends React.Component {
|
||||
|
||||
render() {
|
||||
const { ticket, userStaff, userId, editable, allowAttachments, assignmentAllowed } = this.props;
|
||||
const showResponseField = (!ticket.closed && (editable || !assignmentAllowed));
|
||||
const { editTitle, loading, edit, editId } = this.state;
|
||||
const { closed, author, content, date, edited, file, events} = ticket;
|
||||
const showResponseField = (!closed && (editable || !assignmentAllowed));
|
||||
const lastCommentIndex = events.map(
|
||||
(event, index) => {
|
||||
return {...event, index}}
|
||||
).filter(
|
||||
(event) => event.type === "COMMENT"
|
||||
).at(-1).index;
|
||||
|
||||
const eventsWithModifiedComments = events.map(
|
||||
(event, index) => {
|
||||
return {...event, isLastComment: index === lastCommentIndex && event.type === "COMMENT"};
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="ticket-viewer">
|
||||
{this.state.editTitle ? this.renderEditableTitle() : this.renderTitleHeader()}
|
||||
{editTitle ? this.renderEditableTitle() : this.renderTitleHeader()}
|
||||
{editable ? this.renderEditableHeaders() : this.renderHeaders()}
|
||||
<div className="ticket-viewer__content">
|
||||
<TicketEvent
|
||||
loading={this.state.loading}
|
||||
loading={loading}
|
||||
type="COMMENT"
|
||||
author={ticket.author}
|
||||
content={userStaff ? MentionsParser.parse(ticket.content) : ticket.content}
|
||||
isLastComment={!events.filter(event => event.type === "COMMENT").length}
|
||||
author={author}
|
||||
isTicketClosed={closed}
|
||||
content={userStaff ? MentionsParser.parse(content) : content}
|
||||
userStaff={userStaff}
|
||||
userId={userId}
|
||||
date={ticket.date}
|
||||
date={date}
|
||||
onEdit={this.onEdit.bind(this,0)}
|
||||
edited={ticket.edited}
|
||||
file={ticket.file}
|
||||
edit={this.state.edit && this.state.editId == 0}
|
||||
edited={edited}
|
||||
file={file}
|
||||
edit={edit && editId == 0}
|
||||
onToggleEdit={this.onToggleEdit.bind(this, 0)}
|
||||
allowAttachments={allowAttachments} />
|
||||
</div>
|
||||
<div className="ticket-viewer__comments">
|
||||
{ticket.events && ticket.events.map(this.renderTicketEvent.bind(this))}
|
||||
{eventsWithModifiedComments && eventsWithModifiedComments.map(this.renderTicketEvent.bind(this, closed))}
|
||||
</div>
|
||||
{showResponseField ? this.renderResponseField() : this.renderReopenCloseButtons()}
|
||||
</div>
|
||||
@ -405,22 +421,26 @@ class TicketViewer extends React.Component {
|
||||
return <Button type='link' size="medium" onClick={() => this.setState({["edit"+option]: false})}>{i18n('CLOSE')}</Button>
|
||||
}
|
||||
|
||||
renderTicketEvent(options, index) {
|
||||
renderTicketEvent(isTicketClosed, ticketEventObject, index) {
|
||||
const { userStaff, ticket, userId, allowAttachments } = this.props;
|
||||
const { edit, editId } = this.state;
|
||||
const { content, author, id} = ticketEventObject;
|
||||
|
||||
if(userStaff && typeof options.content === 'string') {
|
||||
options.content = MentionsParser.parse(options.content);
|
||||
if(userStaff && typeof content === 'string') {
|
||||
ticketEventObject.content = MentionsParser.parse(content);
|
||||
}
|
||||
|
||||
return (
|
||||
<TicketEvent
|
||||
{...options}
|
||||
author={(!_.isEmpty(options.author)) ? options.author : ticket.author}
|
||||
{...ticketEventObject}
|
||||
isLastComment={ticketEventObject.isLastComment}
|
||||
author={(!_.isEmpty(author)) ? author : ticket.author}
|
||||
userStaff={userStaff}
|
||||
isTicketClosed={isTicketClosed}
|
||||
userId={userId}
|
||||
onEdit={this.onEdit.bind(this, options.id)}
|
||||
edit={this.state.edit && this.state.editId == options.id}
|
||||
onToggleEdit={this.onToggleEdit.bind(this, options.id)}
|
||||
onEdit={this.onEdit.bind(this, id)}
|
||||
edit={edit && editId == id}
|
||||
onToggleEdit={this.onToggleEdit.bind(this, id)}
|
||||
key={index}
|
||||
allowAttachments={allowAttachments} />
|
||||
);
|
||||
@ -742,9 +762,9 @@ class TicketViewer extends React.Component {
|
||||
const data = {};
|
||||
|
||||
if(ticketeventid) {
|
||||
data.ticketEventId = ticketeventid
|
||||
data.ticketEventId = ticketeventid;
|
||||
} else {
|
||||
data.ticketNumber = this.props.ticket.ticketNumber
|
||||
data.ticketNumber = this.props.ticket.ticketNumber;
|
||||
}
|
||||
|
||||
API.call({
|
||||
|
@ -50,22 +50,30 @@ class EditCommentController extends Controller {
|
||||
$user = Controller::getLoggedUser();
|
||||
$newcontent = Controller::request('content', true);
|
||||
$ticketNumberLog = null;
|
||||
|
||||
$ticketevent = Ticketevent::getTicketEvent(Controller::request('ticketEventId'));
|
||||
$ticket = Ticket::getByTicketNumber(Controller::request('ticketNumber'));
|
||||
|
||||
if(!Controller::isStaffLogged() && ($user->id !== $ticketevent->authorUserId && $user->id !== $ticket->authorId ) ){
|
||||
throw new RequestException(ERRORS::NO_PERMISSION);
|
||||
}
|
||||
|
||||
if(Controller::isStaffLogged()){
|
||||
if(!$ticketevent->isNull()) {
|
||||
$ticket = $ticketevent->ticket;
|
||||
$ticket = Ticket::getDataStore($ticketevent->ticketId);
|
||||
} else {
|
||||
$ticket = Ticket::getByTicketNumber(Controller::request('ticketNumber'));
|
||||
}
|
||||
|
||||
if(!$user->canManageTicket($ticket)) {
|
||||
if(!Controller::isStaffLogged() && $user->id !== $ticketevent->authorUserId && $user->id !== $ticket->authorId) {
|
||||
throw new RequestException(ERRORS::NO_PERMISSION);
|
||||
}
|
||||
|
||||
if(Controller::isStaffLogged() && !$user->canManageTicket($ticket)) {
|
||||
throw new RequestException(ERRORS::NO_PERMISSION);
|
||||
}
|
||||
|
||||
if(!$ticketevent->isNull()) {
|
||||
if($ticketevent->type !== "COMMENT" || $ticket->closed || $ticket->getLatestEventOfType("COMMENT")['id'] !== $ticketevent->id) {
|
||||
throw new RequestException(ERRORS::INVALID_TICKET_EVENT);
|
||||
}
|
||||
} else {
|
||||
if(sizeof($ticket->getEventsOfType("COMMENT"))) {
|
||||
throw new RequestException(ERRORS::INVALID_TICKET_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$ticketevent->isNull()){
|
||||
|
@ -233,4 +233,23 @@ class Ticket extends DataStore {
|
||||
public function isOwner($user) {
|
||||
return !$user->isNull() && $this->owner && $user->id == $this->owner->id && ($user instanceof Staff);
|
||||
}
|
||||
|
||||
public function getEventsOfType($type) {
|
||||
$ticketEvents = $this->eventsToArray();
|
||||
$filteredEventsList = [];
|
||||
|
||||
foreach($ticketEvents as $ticketEvent) {
|
||||
if($ticketEvent['type'] == $type) {
|
||||
array_push($filteredEventsList, $ticketEvent);
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredEventsList;
|
||||
}
|
||||
|
||||
public function getLatestEventOfType($type) {
|
||||
$filteredEventsList = $this->getEventsOfType($type);
|
||||
|
||||
return end($filteredEventsList);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user