diff --git a/client/src/app-components/ticket-event.js b/client/src/app-components/ticket-event.js index 94ce88aa..25413e91 100644 --- a/client/src/app-components/ticket-event.js +++ b/client/src/app-components/ticket-event.js @@ -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 ( -
-
- {((this.props.author.id == this.props.userId && this.props.author.staff == this.props.userStaff) || this.props.userStaff) ? this.renderEditIcon() : null} +
+
+ {(id == userId && staff == userStaff && isLastComment && !isTicketClosed) ? this.renderEditIcon() : null }
) } diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index cd5fedce..bbdc8667 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -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 (
- {this.state.editTitle ? this.renderEditableTitle() : this.renderTitleHeader()} + {editTitle ? this.renderEditableTitle() : this.renderTitleHeader()} {editable ? this.renderEditableHeaders() : this.renderHeaders()}
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} />
- {ticket.events && ticket.events.map(this.renderTicketEvent.bind(this))} + {eventsWithModifiedComments && eventsWithModifiedComments.map(this.renderTicketEvent.bind(this, closed))}
{showResponseField ? this.renderResponseField() : this.renderReopenCloseButtons()}
@@ -405,22 +421,26 @@ class TicketViewer extends React.Component { return } - 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 ( ); @@ -735,16 +755,16 @@ class TicketViewer extends React.Component { }) } - onEdit(ticketeventid,{content}) { + onEdit(ticketeventid, {content}) { this.setState({ loading: true }); const data = {}; - if(ticketeventid){ - data.ticketEventId = ticketeventid - }else{ - data.ticketNumber = this.props.ticket.ticketNumber + if(ticketeventid) { + data.ticketEventId = ticketeventid; + } else { + data.ticketNumber = this.props.ticket.ticketNumber; } API.call({ diff --git a/server/controllers/ticket/edit-comment.php b/server/controllers/ticket/edit-comment.php index b0c1423e..faf7a3b9 100644 --- a/server/controllers/ticket/edit-comment.php +++ b/server/controllers/ticket/edit-comment.php @@ -50,21 +50,29 @@ 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 ) ){ + if(!$ticketevent->isNull()) { + $ticket = Ticket::getDataStore($ticketevent->ticketId); + } else { + $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; - } + if(Controller::isStaffLogged() && !$user->canManageTicket($ticket)) { + throw new RequestException(ERRORS::NO_PERMISSION); + } - if(!$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); } } diff --git a/server/models/Ticket.php b/server/models/Ticket.php index 0e8e160e..9201c1b8 100755 --- a/server/models/Ticket.php +++ b/server/models/Ticket.php @@ -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); + } }