diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index cf8845a05b967228219011bea2d6f1b99c961813..a76aedaa23f8b240a3a653c334e3ddd235dd9052 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -1689,7 +1689,9 @@ ServerConnector.removeComment = function (params) { var queryParams = { commentId: params.commentId }; - var filterParams = {}; + var filterParams = { + reason: params.reason + }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; return self.sendDeleteRequest(self.deleteCommentUrl(queryParams), filterParams); diff --git a/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js b/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js index 75e221292c8dc03e90a558b016c03445d63e2054..424b951e96625d123243b3dc780e8fd92dfe28dc 100644 --- a/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/CommentsAdminPanel.js @@ -19,86 +19,86 @@ function CommentsAdminPanel(params) { CommentsAdminPanel.prototype = Object.create(AbstractAdminPanel.prototype); CommentsAdminPanel.prototype.constructor = CommentsAdminPanel; -CommentsAdminPanel.prototype._createGui = function() { +CommentsAdminPanel.prototype._createGui = function () { var self = this; var projectsDiv = Functions.createElement({ - type : "div", + type: "div", }); self.getElement().appendChild(projectsDiv); var dataDiv = Functions.createElement({ - type : "div", - style : "display:table", + type: "div", + style: "display:table", }); projectsDiv.appendChild(dataDiv); var commentsCell = Functions.createElement({ - type : "div", - style : "display:table-cell;width:100%;vertical-align:top", + type: "div", + style: "display:table-cell;width:100%;vertical-align:top", }); projectsDiv.appendChild(commentsCell); var commentsTable = Functions.createElement({ - type : "table", - name : "commentsTable", - className : "display", - style : "width:100%", + type: "table", + name: "commentsTable", + className: "display", + style: "width:100%", }); commentsCell.appendChild(commentsTable); $(commentsTable).DataTable({ - columns : [ { - title : 'Id', + columns: [{ + title: 'Id', }, { - title : 'Title', + title: 'Title', }, { - title : 'Author', + title: 'Author', }, { - title : 'Email', + title: 'Email', }, { - title : 'Content', + title: 'Content', }, { - title : 'Removed', + title: 'Removed', }, { - title : 'Pinned', - }, ], + title: 'Pinned', + },], }); var projectsCell = Functions.createElement({ - type : "div", - style : "display:table-cell", + type: "div", + style: "display:table-cell", }); projectsDiv.appendChild(projectsCell); var selectProject = Functions.createElement({ - type : "select", - name : "projectSelect", + type: "select", + name: "projectSelect", }); selectProject.size = "12"; - selectProject.onchange = function() { + selectProject.onchange = function () { return self.onProjectChange(); }; projectsCell.appendChild(Functions.createElement({ - type : "h3", - content : "Project", + type: "h3", + content: "Project", })); projectsCell.appendChild(selectProject); }; -CommentsAdminPanel.prototype.init = function() { +CommentsAdminPanel.prototype.init = function () { var self = this; return self.refreshProjects(); }; -CommentsAdminPanel.prototype.refreshProjects = function() { +CommentsAdminPanel.prototype.refreshProjects = function () { var self = this; var projectSelect = $("[name='projectSelect']", self.getElement())[0]; - return ServerConnector.getProjects().then(function(projects) { + return ServerConnector.getProjects().then(function (projects) { while (projectSelect.firstChild) { projectSelect.removeChild(projectSelect.firstChild); } - projects.sort(function(project1, project2) { + projects.sort(function (project1, project2) { if (project1.getProjectId() < project2.getProjectId()) { return -1; } else if (project1.getProjectId() > project2.getProjectId()) { @@ -115,45 +115,50 @@ CommentsAdminPanel.prototype.refreshProjects = function() { projectSelect.appendChild(new Option(name, value)); } return ServerConnector.getProjectId(); - }).then(function(projectId) { + }).then(function (projectId) { projectSelect.value = projectId; return self.onProjectChange(); }); }; -CommentsAdminPanel.prototype.getSelectedProjectId = function() { +CommentsAdminPanel.prototype.getSelectedProjectId = function () { var projectSelect = $("[name='projectSelect']", this.getElement())[0]; return projectSelect.value; }; -CommentsAdminPanel.prototype.onProjectChange = function() { +CommentsAdminPanel.prototype.onProjectChange = function () { var self = this; return ServerConnector.getComments({ - projectId : self.getSelectedProjectId(), - }).then(function(comments) { + projectId: self.getSelectedProjectId() + }).then(function (comments) { var dataTable = $($("[name='commentsTable']", self.getElement())[0]).DataTable(); var data = []; for (var i = 0; i < comments.length; i++) { data.push(self.commentToTableRow(comments[i])); } dataTable.clear().rows.add(data).draw(); - $("[name='commentsTable']", self.getElement()).on("click", "[name='removeComment']", function() { + $("[name='commentsTable']", self.getElement()).on("click", "[name='removeComment']", function () { var button = this; - return ServerConnector.removeComment({ - commentId : $(button).attr("data") - }).then(function() { - $(button).after("<span>YES</span>"); - button.style.display = "none"; - }); + return self.askConfirmRemoval().then(function (param) { + if (param.status) { + return ServerConnector.removeComment({ + commentId: $(button).attr("data"), + reason: param.reason + }).then(function () { + $(button).after("<span>YES (" + param.reason + ")</span>"); + button.style.display = "none"; + }); + } + }) }); }); }; -CommentsAdminPanel.prototype.commentToTableRow = function(comment) { +CommentsAdminPanel.prototype.commentToTableRow = function (comment) { var self = this; var projectId = self.getSelectedProjectId(); - var toYesNo = function(val) { + var toYesNo = function (val) { if (val) { return "YES"; } else { @@ -163,10 +168,10 @@ CommentsAdminPanel.prototype.commentToTableRow = function(comment) { var title = null; if (!comment.isRemoved()) { var commentLink = "index.xhtml?id=" + projectId + // - "&x=" + comment.getCoordinates().x + // - "&y=" + comment.getCoordinates().y + // - "&zoom=12" + // - "&comments=on"; + "&x=" + comment.getCoordinates().x + // + "&y=" + comment.getCoordinates().y + // + "&zoom=12" + // + "&comments=on"; title = "<a href='" + commentLink + "' target='" + projectId + "'>" + comment.getTitle() + "</a>"; } else { title = comment.getTitle(); @@ -174,7 +179,7 @@ CommentsAdminPanel.prototype.commentToTableRow = function(comment) { var remove = null; if (comment.isRemoved()) { - remove = "YES"; + remove = "YES (" + comment.getRemoveReason() + ")"; } else { remove = "<button name='removeComment' data='" + comment.getId() + "'>REMOVE</button>"; } @@ -189,22 +194,41 @@ CommentsAdminPanel.prototype.commentToTableRow = function(comment) { email = "N/A"; } - var row = [ comment.getId(), // - title, // - author, // - email, // - comment.getContent(), // - remove, // - toYesNo(comment.isPinned()) ]; + var row = [comment.getId(), // + title, // + author, // + email, // + comment.getContent(), // + remove, // + toYesNo(comment.isPinned())]; return row; }; CommentsAdminPanel.prototype.destroy = function () { - var self = this; - var table = $("[name='commentsTable']", self.getElement())[0]; - if ($.fn.DataTable.isDataTable(table)) { - $(table).DataTable().destroy(); - } + var self = this; + var table = $("[name='commentsTable']", self.getElement())[0]; + if ($.fn.DataTable.isDataTable(table)) { + $(table).DataTable().destroy(); + } +}; + +CommentsAdminPanel.prototype.askConfirmRemoval = function () { + return new Promise(function (resolve) { + $('<form><input type="text" style="z-index:10000" name="name"><br></form>').dialog({ + modal: true, + title: "Why do you want to remove this comment?", + buttons: { + 'OK': function () { + $(this).dialog('close'); + resolve({reason: $('input[name="name"]').val(), status: true}); + }, + 'Cancel': function () { + $(this).dialog('close'); + resolve({status: false}); + } + } + }); + }) }; module.exports = CommentsAdminPanel; diff --git a/frontend-js/src/main/js/map/data/Comment.js b/frontend-js/src/main/js/map/data/Comment.js index 735e508c1de3989d1bd2be8460eb3e0de856fbce..b075e577929e33fde2d370162b5a1b1a6955dbf4 100644 --- a/frontend-js/src/main/js/map/data/Comment.js +++ b/frontend-js/src/main/js/map/data/Comment.js @@ -7,10 +7,11 @@ function Comment(javaObject) { id : javaObject.elementId, type : javaObject.type, modelId : javaObject.modelId, - icon : javaObject.icon, + icon : javaObject.icon })); this.setId(javaObject.id); this.setRemoved(javaObject.removed); + this.setRemoveReason(javaObject.removeReason); this.setPinned(javaObject.pinned); if (javaObject.title !== undefined) { @@ -82,5 +83,11 @@ Comment.prototype.setEmail = function(email) { Comment.prototype.getEmail = function() { return this._email; }; +Comment.prototype.setRemoveReason = function(removeReason) { + this._removeReason = removeReason; +}; +Comment.prototype.getRemoveReason = function() { + return this._removeReason; +}; module.exports = Comment; diff --git a/frontend-js/src/main/js/map/data/Mesh.js b/frontend-js/src/main/js/map/data/Mesh.js index 612111fec621ccab07cc808cd37cf4125afedb83..500ef3a9a107101e11642b1478ca03731a5652a7 100644 --- a/frontend-js/src/main/js/map/data/Mesh.js +++ b/frontend-js/src/main/js/map/data/Mesh.js @@ -9,29 +9,28 @@ function Mesh(jsonObject) { } Mesh.prototype.setSynonyms = function (synonyms) { - this.synonyms = synonyms; + this._synonyms = synonyms; }; Mesh.prototype.getSynonyms = function () { - return this.synonyms; + return this._synonyms; }; Mesh.prototype.setName = function (name) { - this.name = name; + this._name = name; }; Mesh.prototype.getName = function () { - return this.name; + return this._name; }; Mesh.prototype.setId = function (id) { - this.id = id; + this._id = id; }; Mesh.prototype.getId = function () { - return this.id; + return this._id; }; Mesh.prototype.setDescription = function (description) { - this.description = description; + this._description = description; }; Mesh.prototype.getDescription = function () { - return this.description; + return this._description; }; - module.exports = Mesh; diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java b/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java index e210ca049b46b67c266fa57be45dfacf142aa0c4..7e9ca40a76fc9c562bd22f607d5a79f71536adf3 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/BaseController.java @@ -23,62 +23,70 @@ import lcsb.mapviewer.common.Configuration; import lcsb.mapviewer.common.exception.InvalidStateException; public abstract class BaseController { - private Logger logger = Logger.getLogger(BaseController.class); + private Logger logger = Logger.getLogger(BaseController.class); - private ObjectMapper mapper = new ObjectMapper(); + private ObjectMapper mapper = new ObjectMapper(); - @ExceptionHandler({ Exception.class }) - public ResponseEntity<Object> handleException(Exception e, WebRequest request) { - if (e instanceof lcsb.mapviewer.services.SecurityException) { - return new ResponseEntity<Object>("{\"error\" : \"Access denied.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.FORBIDDEN); - } else if (e instanceof ObjectNotFoundException) { - return new ResponseEntity<Object>("{\"error\" : \"Object not found.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.NOT_FOUND); - } else if (e instanceof ObjectExistsException) { - return new ResponseEntity<Object>( - "{\"error\" : \"Object already exists.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.CONFLICT); - } else if (e instanceof QueryException) { - logger.error(e, e); - return new ResponseEntity<Object>( - "{\"error\" : \"Query server error.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.BAD_REQUEST); - } else if (e instanceof ServletRequestBindingException && e.getMessage().indexOf(Configuration.AUTH_TOKEN) >= 0) { - return new ResponseEntity<Object>("{\"error\" : \"Access denied.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.FORBIDDEN); - } else { - logger.error(e, e); - return new ResponseEntity<Object>( - "{\"error\" : \"Internal server error.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); - } - } + @ExceptionHandler({ Exception.class }) + public ResponseEntity<Object> handleException(Exception e, WebRequest request) { + if (e instanceof lcsb.mapviewer.services.SecurityException) { + return new ResponseEntity<Object>("{\"error\" : \"Access denied.\",\"reason\":\"" + e.getMessage() + "\"}", + new HttpHeaders(), HttpStatus.FORBIDDEN); + } else if (e instanceof ObjectNotFoundException) { + return new ResponseEntity<Object>("{\"error\" : \"Object not found.\",\"reason\":\"" + e.getMessage() + "\"}", + new HttpHeaders(), HttpStatus.NOT_FOUND); + } else if (e instanceof ObjectExistsException) { + return new ResponseEntity<Object>( + "{\"error\" : \"Object already exists.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), + HttpStatus.CONFLICT); + } else if (e instanceof QueryException) { + logger.error(e, e); + return new ResponseEntity<Object>("{\"error\" : \"Query server error.\",\"reason\":\"" + e.getMessage() + "\"}", + new HttpHeaders(), HttpStatus.BAD_REQUEST); + } else if (e instanceof ServletRequestBindingException && e.getMessage().indexOf(Configuration.AUTH_TOKEN) >= 0) { + return new ResponseEntity<Object>("{\"error\" : \"Access denied.\",\"reason\":\"" + e.getMessage() + "\"}", + new HttpHeaders(), HttpStatus.FORBIDDEN); + } else { + logger.error(e, e); + return new ResponseEntity<Object>( + "{\"error\" : \"Internal server error.\",\"reason\":\"" + e.getMessage() + "\"}", new HttpHeaders(), + HttpStatus.INTERNAL_SERVER_ERROR); + } + } - public Map<String, Object> parseBody(String body) throws IOException, JsonParseException, JsonMappingException { - ObjectNode result = mapper.readValue(body, ObjectNode.class); - return mapper.convertValue(result, Map.class); - } + public Map<String, Object> parseBody(String body) throws IOException, JsonParseException, JsonMappingException { + if (body == null || body.isEmpty()) { + return new HashMap<>(); + } + ObjectNode result = mapper.readValue(body, ObjectNode.class); + return mapper.convertValue(result, Map.class); + } - protected Map<String, Object> getData(Map<String, Object> node, String objectName) { - return (Map<String, Object>) node.get(objectName); - } + protected Map<String, Object> getData(Map<String, Object> node, String objectName) { + return (Map<String, Object>) node.get(objectName); + } - protected Map<String, String> parsePostBody(String body) { - Map<String, String> result = new HashMap<>(); - String[] parameters = body.split("&"); - for (String string : parameters) { - int position = string.indexOf("="); - if (position < 0) { - position = string.length(); - } - String key = string.substring(0, position); - String value = null; - if (position < string.length()) { - value = string.substring(position + 1, string.length()); - try { - value = URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new InvalidStateException("Cannot decode input", e); - } - } - result.put(key, value); - } - return result; - } + protected Map<String, String> parsePostBody(String body) { + Map<String, String> result = new HashMap<>(); + String[] parameters = body.split("&"); + for (String string : parameters) { + int position = string.indexOf("="); + if (position < 0) { + position = string.length(); + } + String key = string.substring(0, position); + String value = null; + if (position < string.length()) { + value = string.substring(position + 1, string.length()); + try { + value = URLDecoder.decode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new InvalidStateException("Cannot decode input", e); + } + } + result.put(key, value); + } + return result; + } } diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java index 2617a3c3f8df33777cc5dabd9b693ee7e81ef069..c941446e661d92e6d34b8f4c33c21f4bd4318d51 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentController.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.api.projects.comments; import java.awt.geom.Point2D; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -8,11 +9,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + import lcsb.mapviewer.api.BaseController; import lcsb.mapviewer.api.QueryException; import lcsb.mapviewer.common.Configuration; @@ -22,152 +27,157 @@ import lcsb.mapviewer.services.search.data.ElementIdentifier.ElementIdentifierTy @RestController public class CommentController extends BaseController { - @Autowired - private CommentRestImpl commentController; - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public List<Map<String, Object>> getComments(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @RequestParam(value = "columns", defaultValue = "") String columns, // - @RequestParam(value = "removed", defaultValue = "") String removed // - ) throws SecurityException, QueryException { - return commentController.getCommentList(token, projectId, columns, "", "", removed); - } - - @RequestMapping(value = "/projects/{projectId}/comments/{commentId}/", method = { RequestMethod.DELETE }, produces = { MediaType.APPLICATION_JSON_VALUE }) - public Map<String, Object> removeComment(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @PathVariable(value = "commentId") String commentId // - ) throws SecurityException, QueryException { - return commentController.removeComment(token, projectId, commentId); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { RequestMethod.GET }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public List<Map<String, Object>> getCommentsByReaction(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @RequestParam(value = "columns", defaultValue = "") String columns, // - @PathVariable(value = "reactionId") String reactionId, // - @RequestParam(value = "removed", defaultValue = "") String removed // - ) throws SecurityException, QueryException { - return commentController.getCommentList(token, projectId, columns, reactionId, ElementIdentifierType.REACTION.getJsName(), removed); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { RequestMethod.GET }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public List<Map<String, Object>> getCommentsByElement(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @RequestParam(value = "columns", defaultValue = "") String columns, // - @PathVariable(value = "elementId") String elementId, // - @RequestParam(value = "removed", defaultValue = "") String removed // - ) throws SecurityException, QueryException { - return commentController.getCommentList(token, projectId, columns, elementId, ElementIdentifierType.ALIAS.getJsName(), removed); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates:.+}", method = { RequestMethod.GET }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public List<Map<String, Object>> getCommentsByPoint(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @RequestParam(value = "columns", defaultValue = "") String columns, // - @PathVariable(value = "coordinates") String coordinates, // - @RequestParam(value = "removed", defaultValue = "") String removed // - ) throws SecurityException, QueryException { - return commentController.getCommentList(token, projectId, columns, coordinates, ElementIdentifierType.POINT.getJsName(), removed); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { RequestMethod.POST }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public Map<String, Object> addCommentForElement(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @PathVariable(value = "elementId") String elementId, // - @RequestParam(value = "name") String name, // - @RequestParam(value = "email") String email, // - @RequestParam(value = "content") String content, // - @RequestParam(value = "pinned", defaultValue = "true") String pinned, // - @RequestParam(value = "coordinates") String coordinates, // - @PathVariable(value = "modelId") String modelId // - ) throws SecurityException, QueryException { - Point2D pointCoordinates = parseCoordinates(coordinates); - return commentController.addComment( - token, projectId, ElementIdentifierType.ALIAS.getJsName(), elementId, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates, - modelId); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { RequestMethod.POST }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public Map<String, Object> addCommentForReaction(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @PathVariable(value = "reactionId") String reactionId, // - @RequestParam(value = "name") String name, // - @RequestParam(value = "email") String email, // - @RequestParam(value = "content") String content, // - @RequestParam(value = "pinned", defaultValue = "true") String pinned, // - @RequestParam(value = "coordinates") String coordinates, // - @PathVariable(value = "modelId") String modelId // - ) throws SecurityException, QueryException { - Point2D pointCoordinates = parseCoordinates(coordinates); - return commentController.addComment( - token, projectId, ElementIdentifierType.REACTION.getJsName(), reactionId, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates, - modelId); - } - - @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates}", method = { RequestMethod.POST }, - produces = { MediaType.APPLICATION_JSON_VALUE }) - public Map<String, Object> addCommentForPoint(// - @CookieValue(value = Configuration.AUTH_TOKEN) String token, // - @PathVariable(value = "projectId") String projectId, // - @RequestParam(value = "name") String name, // - @RequestParam(value = "email") String email, // - @RequestParam(value = "content") String content, // - @RequestParam(value = "pinned", defaultValue = "true") String pinned, // - @PathVariable(value = "coordinates") String coordinates, // - @PathVariable(value = "modelId") String modelId // - ) throws SecurityException, QueryException { - Point2D pointCoordinates = parseCoordinates(coordinates); - return commentController.addComment( - token, projectId, ElementIdentifierType.POINT.getJsName(), coordinates, name, email, content, pinned.toLowerCase().equals("true"), pointCoordinates, - modelId); - } - - private Point2D parseCoordinates(String coordinates) throws QueryException { - String[] tmp = coordinates.split(","); - if (tmp.length != 2) { - throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'"); - } - Double x = null; - Double y = null; - try { - x = Double.valueOf(tmp[0]); - y = Double.valueOf(tmp[1]); - } catch (NumberFormatException e) { - throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e); - } - Point2D pointCoordinates = new Point2D.Double(x, y); - return pointCoordinates; - } - - /** - * @return the overlayController - * @see #commentController - */ - public CommentRestImpl getOverlayController() { - return commentController; - } - - /** - * @param overlayController - * the overlayController to set - * @see #commentController - */ - public void setOverlayController(CommentRestImpl overlayController) { - this.commentController = overlayController; - } + @Autowired + private CommentRestImpl commentController; + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public List<Map<String, Object>> getComments(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @RequestParam(value = "columns", defaultValue = "") String columns, // + @RequestParam(value = "removed", defaultValue = "") String removed // + ) throws SecurityException, QueryException { + return commentController.getCommentList(token, projectId, columns, "", "", removed); + } + + @RequestMapping(value = "/projects/{projectId}/comments/{commentId}/", method = { RequestMethod.DELETE }, produces = { + MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> removeComment(// + @RequestBody(required = false) String body, // + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @PathVariable(value = "commentId") String commentId // + ) throws SecurityException, QueryException, JsonParseException, JsonMappingException, IOException { + Map<String, Object> node = parseBody(body); + String reason = (String) node.get("reason"); + return commentController.removeComment(token, projectId, commentId, reason); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public List<Map<String, Object>> getCommentsByReaction(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @RequestParam(value = "columns", defaultValue = "") String columns, // + @PathVariable(value = "reactionId") String reactionId, // + @RequestParam(value = "removed", defaultValue = "") String removed // + ) throws SecurityException, QueryException { + return commentController.getCommentList(token, projectId, columns, reactionId, + ElementIdentifierType.REACTION.getJsName(), removed); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public List<Map<String, Object>> getCommentsByElement(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @RequestParam(value = "columns", defaultValue = "") String columns, // + @PathVariable(value = "elementId") String elementId, // + @RequestParam(value = "removed", defaultValue = "") String removed // + ) throws SecurityException, QueryException { + return commentController.getCommentList(token, projectId, columns, elementId, + ElementIdentifierType.ALIAS.getJsName(), removed); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates:.+}", method = { + RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public List<Map<String, Object>> getCommentsByPoint(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @RequestParam(value = "columns", defaultValue = "") String columns, // + @PathVariable(value = "coordinates") String coordinates, // + @RequestParam(value = "removed", defaultValue = "") String removed // + ) throws SecurityException, QueryException { + return commentController.getCommentList(token, projectId, columns, coordinates, + ElementIdentifierType.POINT.getJsName(), removed); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/elements/{elementId}", method = { + RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> addCommentForElement(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @PathVariable(value = "elementId") String elementId, // + @RequestParam(value = "name") String name, // + @RequestParam(value = "email") String email, // + @RequestParam(value = "content") String content, // + @RequestParam(value = "pinned", defaultValue = "true") String pinned, // + @RequestParam(value = "coordinates") String coordinates, // + @PathVariable(value = "modelId") String modelId // + ) throws SecurityException, QueryException { + Point2D pointCoordinates = parseCoordinates(coordinates); + return commentController.addComment(token, projectId, ElementIdentifierType.ALIAS.getJsName(), elementId, name, + email, content, pinned.toLowerCase().equals("true"), pointCoordinates, modelId); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/bioEntities/reactions/{reactionId}", method = { + RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> addCommentForReaction(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @PathVariable(value = "reactionId") String reactionId, // + @RequestParam(value = "name") String name, // + @RequestParam(value = "email") String email, // + @RequestParam(value = "content") String content, // + @RequestParam(value = "pinned", defaultValue = "true") String pinned, // + @RequestParam(value = "coordinates") String coordinates, // + @PathVariable(value = "modelId") String modelId // + ) throws SecurityException, QueryException { + Point2D pointCoordinates = parseCoordinates(coordinates); + return commentController.addComment(token, projectId, ElementIdentifierType.REACTION.getJsName(), reactionId, name, + email, content, pinned.toLowerCase().equals("true"), pointCoordinates, modelId); + } + + @RequestMapping(value = "/projects/{projectId}/comments/models/{modelId}/points/{coordinates}", method = { + RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE }) + public Map<String, Object> addCommentForPoint(// + @CookieValue(value = Configuration.AUTH_TOKEN) String token, // + @PathVariable(value = "projectId") String projectId, // + @RequestParam(value = "name") String name, // + @RequestParam(value = "email") String email, // + @RequestParam(value = "content") String content, // + @RequestParam(value = "pinned", defaultValue = "true") String pinned, // + @PathVariable(value = "coordinates") String coordinates, // + @PathVariable(value = "modelId") String modelId // + ) throws SecurityException, QueryException { + Point2D pointCoordinates = parseCoordinates(coordinates); + return commentController.addComment(token, projectId, ElementIdentifierType.POINT.getJsName(), coordinates, name, + email, content, pinned.toLowerCase().equals("true"), pointCoordinates, modelId); + } + + private Point2D parseCoordinates(String coordinates) throws QueryException { + String[] tmp = coordinates.split(","); + if (tmp.length != 2) { + throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'"); + } + Double x = null; + Double y = null; + try { + x = Double.valueOf(tmp[0]); + y = Double.valueOf(tmp[1]); + } catch (NumberFormatException e) { + throw new QueryException("Coordinates must be in the format: 'xxx.xx,yyy.yy'", e); + } + Point2D pointCoordinates = new Point2D.Double(x, y); + return pointCoordinates; + } + + /** + * @return the overlayController + * @see #commentController + */ + public CommentRestImpl getOverlayController() { + return commentController; + } + + /** + * @param overlayController + * the overlayController to set + * @see #commentController + */ + public void setOverlayController(CommentRestImpl overlayController) { + this.commentController = overlayController; + } } \ No newline at end of file diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java index 192efa5d6d25fc01a5b9c59740efcd4613eb49ea..b35bf061173f85c9524bb6207169d06a7ff40df9 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/comments/CommentRestImpl.java @@ -130,6 +130,8 @@ public class CommentRestImpl extends BaseRestImpl { value = comment.isDeleted(); } else if (column.equals("coord")) { value = getCoordinates(comment); + } else if (column.equals("removereason")) { + value = comment.getRemoveReason(); } else if (column.equals("type")) { value = getType(comment); } else if (column.equals("icon")) { @@ -240,6 +242,7 @@ public class CommentRestImpl extends BaseRestImpl { columnsSet.add("pinned"); columnsSet.add("author"); columnsSet.add("email"); + columnsSet.add("removeReason"); } } else { for (String str : columns.split(",")) { @@ -328,7 +331,7 @@ public class CommentRestImpl extends BaseRestImpl { return preparedComment(comment, createCommentColumnSet("", isAdmin), isAdmin); } - public Map<String, Object> removeComment(String token, String projectId, String commentId) + public Map<String, Object> removeComment(String token, String projectId, String commentId, String reason) throws SecurityException, QueryException { AuthenticationToken authenticationToken = getUserService().getToken(token); Project project = getProjectService().getProjectByProjectId(projectId, authenticationToken); @@ -340,7 +343,7 @@ public class CommentRestImpl extends BaseRestImpl { throw new ObjectNotFoundException("Comment with given id doesn't exist"); } - commentService.deleteComment(comment, authenticationToken); + commentService.deleteComment(comment, authenticationToken, reason); return okStatus(); } diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java b/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java index 08f6daf43d0283ab8e70a941a951e4d4e720ccd1..faf8f766ae94a39b5accd4f67f10098b8d555708 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/CommentService.java @@ -426,11 +426,12 @@ public class CommentService implements ICommentService { } @Override - public void deleteComment(Comment comment, AuthenticationToken token) throws UserAccessException { + public void deleteComment(Comment comment, AuthenticationToken token, String reason) throws UserAccessException { Project project = comment.getModelData().getProject(); boolean editComments = userService.userHasPrivilege(token, PrivilegeType.EDIT_COMMENTS_PROJECT, project); if (editComments || userService.getUserByToken(token).equals(comment.getUser())) { comment.setDeleted(true); + comment.setRemoveReason(reason); commentDao.update(comment); } else { throw new UserAccessException("You have no privileges to remove the comment"); diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java index 06d32a16cc550af0da85dea6377d1931bda5ba79..dd3db2c6beb22011de2f1a352a919a8893a903f5 100644 --- a/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java +++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/ICommentService.java @@ -60,7 +60,7 @@ public interface ICommentService { */ void deleteComment(User loggedUser, String commentId, String reason); - void deleteComment(Comment comment, AuthenticationToken token) throws UserAccessException; + void deleteComment(Comment comment, AuthenticationToken token, String reason) throws UserAccessException; /** * Method returns all comments for a given map.