From 402af565a9b9e36325cdaf3e26ec40f0cccc624a Mon Sep 17 00:00:00 2001
From: LautaroCesso <59095036+LautaroCesso@users.noreply.github.com>
Date: Fri, 26 Nov 2021 17:37:33 -0300
Subject: [PATCH] [DEV-162] Fix ticket comment issues (#1081)
* Fix bug in UI
* Fix bug in backend
* Fix some issues
* Improve coding
* Improve coding
---
client/src/app-components/ticket-event.js | 20 +++----
client/src/app-components/ticket-viewer.js | 66 ++++++++++++++--------
server/controllers/ticket/edit-comment.php | 26 ++++++---
server/models/Ticket.php | 19 +++++++
4 files changed, 89 insertions(+), 42 deletions(-)
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);
+ }
}