From 6977d97332518f8ffac1566c133587e02b27209d Mon Sep 17 00:00:00 2001 From: bancika Date: Thu, 27 Oct 2016 17:53:10 +0200 Subject: [PATCH] send comments functionality --- .../plugins/cloud/model/CommentEntity.java | 34 +-- .../plugins/cloud/model/CommentTree.java | 23 ++ .../plugins/cloud/model/IServiceAPI.java | 14 ++ .../diylc/plugins/cloud/model/UserEntity.java | 2 +- .../cloud/presenter/CloudPresenter.java | 22 +- .../diylc-core/src/org/diylc/utils/Pair.java | 21 ++ .../org/diylc/swing/gui/DialogFactory.java | 2 +- .../plugins/cloud/view/CommentDialog.java | 201 ++++++++++++++++++ .../view/browser/ResultsScrollPanel.java | 37 +++- 9 files changed, 327 insertions(+), 29 deletions(-) create mode 100644 diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentTree.java create mode 100644 diylc/diylc-core/src/org/diylc/utils/Pair.java create mode 100644 diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CommentDialog.java diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentEntity.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentEntity.java index 5a7e5a03..fc6363d0 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentEntity.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentEntity.java @@ -1,9 +1,13 @@ package org.diylc.plugins.cloud.model; -public class CommentEntity { +import java.io.Serializable; + +public class CommentEntity implements Serializable { + + private static final long serialVersionUID = 1L; private int id; - private int userId; + private int parentId; private String username; private String comment; private String postedAt; @@ -16,12 +20,12 @@ public class CommentEntity { this.id = id; } - public int getUserId() { - return userId; + public int getParentId() { + return parentId; } - public void setUserId(int userId) { - this.userId = userId; + public void setParentId(int parentId) { + this.parentId = parentId; } public String getUsername() { @@ -40,12 +44,12 @@ public class CommentEntity { this.comment = comment; } - public String getDate() { + public String getPostedAt() { return postedAt; } - public void setDate(String date) { - this.postedAt = date; + public void setPostedAt(String postedAt) { + this.postedAt = postedAt; } @Override @@ -53,9 +57,9 @@ public class CommentEntity { final int prime = 31; int result = 1; result = prime * result + ((comment == null) ? 0 : comment.hashCode()); - result = prime * result + ((postedAt == null) ? 0 : postedAt.hashCode()); result = prime * result + id; - result = prime * result + userId; + result = prime * result + parentId; + result = prime * result + ((postedAt == null) ? 0 : postedAt.hashCode()); result = prime * result + ((username == null) ? 0 : username.hashCode()); return result; } @@ -74,15 +78,15 @@ public class CommentEntity { return false; } else if (!comment.equals(other.comment)) return false; + if (id != other.id) + return false; + if (parentId != other.parentId) + return false; if (postedAt == null) { if (other.postedAt != null) return false; } else if (!postedAt.equals(other.postedAt)) return false; - if (id != other.id) - return false; - if (userId != other.userId) - return false; if (username == null) { if (other.username != null) return false; diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentTree.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentTree.java new file mode 100644 index 00000000..12c7c0f0 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/CommentTree.java @@ -0,0 +1,23 @@ +package org.diylc.plugins.cloud.model; + +import java.util.ArrayList; +import java.util.List; + +public class CommentTree { + + private CommentEntity rootComment; + private List replies; + + public CommentTree(CommentEntity rootComment) { + this.rootComment = rootComment; + this.replies = new ArrayList(); + } + + public CommentEntity getRootComment() { + return rootComment; + } + + public List getReplies() { + return replies; + } +} diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java index 306b57f4..580dd564 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java @@ -124,6 +124,20 @@ public interface IServiceAPI { @ParamName("diylcVersion") String diylcVersion, @ParamName("keywords") String keywords, @ParamName("thumbnail") File thumbnail, @ParamName("project") File project); + /** + * Posts a comment to the specified project. + * + * @param username + * @param token + * @param machineId + * @param projectId + * @param comment + * @return + */ + String postComment(@ParamName("username") String username, @ParamName("token") String token, + @ParamName("machineId") String machineId, @ParamName("projectId") Integer projectId, + @ParamName("comment") String comment); + /** * @return a {@link List} of available categories. */ diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/UserEntity.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/UserEntity.java index 1efd7d5a..65b23574 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/UserEntity.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/UserEntity.java @@ -11,7 +11,7 @@ public class UserEntity implements Serializable { private String website; private String bio; - public UserEntity(String userName, String email, String website, String bio) { + public UserEntity(String username, String email, String website, String bio) { super(); this.username = username; this.email = email; diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java index 2fcacb2c..79a09a04 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java @@ -152,7 +152,22 @@ public class CloudPresenter { } catch (Exception e) { throw new CloudException(e); } + } + public void postComment(int projectId, String comment) throws CloudException { + String username = ConfigurationManager.getInstance().readString(USERNAME_KEY, null); + String token = ConfigurationManager.getInstance().readString(TOKEN_KEY, null); + + if (username == null || token == null) + throw new CloudException("Login failed. Please try to login again."); + + try { + String res = service.postComment(username, token, getMachineId(), projectId, comment); + if (!res.equals(SUCCESS)) + throw new CloudException(res); + } catch (Exception e) { + throw new CloudException(e); + } } public void createUserAccount(String username, String password, String email, String website, String bio) @@ -185,6 +200,10 @@ public class CloudPresenter { throw new CloudException("Unexpected server response received for category list: " + res.getClass().getName()); } + public String getCurrentUsername() { + return ConfigurationManager.getInstance().readString(USERNAME_KEY, null); + } + public void updatePassword(String oldPassword, String newPassword) throws CloudException { String username = ConfigurationManager.getInstance().readString(USERNAME_KEY, null); @@ -255,7 +274,7 @@ public class CloudPresenter { } } - public List GetComments(int projectId) throws CloudException { + public List getComments(int projectId) throws CloudException { try { Object res = service.getComments(projectId); if (res == null) @@ -273,6 +292,7 @@ public class CloudPresenter { } } + private String getMachineId() { if (machineId == null) { try { diff --git a/diylc/diylc-core/src/org/diylc/utils/Pair.java b/diylc/diylc-core/src/org/diylc/utils/Pair.java new file mode 100644 index 00000000..33a8a703 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/utils/Pair.java @@ -0,0 +1,21 @@ +package org.diylc.utils; + +public class Pair { + + private A first; + private B second; + + public Pair(A first, B second) { + super(); + this.first = first; + this.second = second; + } + + public A getFirst() { + return first; + } + + public B getSecond() { + return second; + } +} diff --git a/diylc/diylc-swing/src/org/diylc/swing/gui/DialogFactory.java b/diylc/diylc-swing/src/org/diylc/swing/gui/DialogFactory.java index 3c80d64b..6964318d 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/gui/DialogFactory.java +++ b/diylc/diylc-swing/src/org/diylc/swing/gui/DialogFactory.java @@ -136,7 +136,7 @@ public class DialogFactory { public LoginDialog createLoginDialog() { LoginDialog dialog = new LoginDialog(mainFrame); return dialog; - } + } public UploadDialog createUploadDialog(IPlugInPort plugInPort, CloudPresenter cloudPresenter) { UploadDialog dialog = new UploadDialog(mainFrame, plugInPort, cloudPresenter); diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CommentDialog.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CommentDialog.java new file mode 100644 index 00000000..9c4ae8b7 --- /dev/null +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CommentDialog.java @@ -0,0 +1,201 @@ +package org.diylc.swing.plugins.cloud.view; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTextArea; + +import org.apache.log4j.Logger; +import org.diylc.common.ITask; +import org.diylc.core.IView; +import org.diylc.plugins.cloud.model.CommentEntity; +import org.diylc.plugins.cloud.model.ProjectEntity; +import org.diylc.plugins.cloud.presenter.CloudException; +import org.diylc.plugins.cloud.presenter.CloudPresenter; +import org.diylc.swing.plugins.cloud.view.browser.CloudBrowserFrame; + +public class CommentDialog extends JDialog { + + private static final String JUST_NOW = "just now"; + + private static final long serialVersionUID = 1L; + + private static final Logger LOG = Logger.getLogger(CommentDialog.class); + + private ProjectEntity project; + private List comments; + private CloudPresenter presenter; + + private JPanel mainPanel; + private JPanel listPanel; + private JTextArea replyArea; + private JButton sendButton; + + private int lastPosition = 0; + + private CloudBrowserFrame owner; + + public CommentDialog(CloudBrowserFrame owner, ProjectEntity project, List comments, + CloudPresenter presenter) { + super(owner, "Comments on " + project.getName()); + this.owner = owner; + this.project = project; + this.comments = comments; + this.presenter = presenter; + setMinimumSize(new Dimension(400, 600)); + setContentPane(getMainPanel()); + pack(); + setLocationRelativeTo(owner); + setModal(true); + if (!presenter.isLoggedIn()) { + getReplyArea().setEnabled(false); + getReplyArea().setText("Must be logged in to reply."); + getSendButton().setEnabled(false); + } + } + + private JPanel getListPanel() { + if (listPanel == null) { + listPanel = new JPanel(new GridBagLayout()); + listPanel.setBackground(Color.white); + for (int i = 0; i < comments.size(); i++) { + CommentEntity c = comments.get(i); + addComment(c); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridy = 10000; + gbc.weighty = 1; + listPanel.add(new JLabel(), gbc); + } + } + return listPanel; + } + + private JPanel getMainPanel() { + if (mainPanel == null) { + mainPanel = new JPanel(new GridBagLayout()); + mainPanel.setBackground(Color.white); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weighty = 3; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.BOTH; + JScrollPane scroll = new JScrollPane(getListPanel()); + scroll.getVerticalScrollBar().setUnitIncrement(16); + mainPanel.add(scroll, gbc); + + // Add components to the bottom + gbc.insets = new Insets(2, 2, 2, 2); + gbc.gridy++; + gbc.weighty = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.LINE_START; + mainPanel.add(new JLabel("Write a reply:"), gbc); + + gbc.gridy++; + gbc.fill = GridBagConstraints.BOTH; + gbc.weighty = 0.5; + mainPanel.add(new JScrollPane(getReplyArea()), gbc); + + gbc.gridy++; + gbc.weighty = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.LINE_END; + mainPanel.add(getSendButton(), gbc); + } + return mainPanel; + } + + private JTextArea getReplyArea() { + if (replyArea == null) { + replyArea = new JTextArea(); + replyArea.setFont(getSendButton().getFont()); + } + return replyArea; + } + + private JButton getSendButton() { + if (sendButton == null) { + sendButton = new JButton("Send Reply"); + sendButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final String comment = getReplyArea().getText().replace("\n", "
"); + if (comment.trim().length() == 0) + owner.showMessage("Cannot post an empty comment.", "Cloud Error", IView.ERROR_MESSAGE); + + owner.executeBackgroundTask(new ITask() { + + @Override + public Void doInBackground() throws Exception { + presenter.postComment(project.getId(), comment); + return null; + } + + @Override + public void failed(Exception e) { + owner.showMessage("Error posting comment.", "Cloud Error", IView.ERROR_MESSAGE); + } + + @Override + public void complete(Void result) { + getReplyArea().setText(""); + CommentEntity newComment = new CommentEntity(); + newComment.setPostedAt(JUST_NOW); + newComment.setUsername(presenter.getCurrentUsername()); + newComment.setComment(comment); + addComment(newComment).requestFocusInWindow(); + getListPanel().revalidate(); + } + }); + } + }); + } + return sendButton; + } + + private JTextArea addComment(CommentEntity c) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.NONE; + gbc.gridx = 0; + gbc.gridy = lastPosition++; + gbc.insets = new Insets(2, 2, 2, 2); + gbc.anchor = GridBagConstraints.LINE_START; + gbc.weightx = 1; + getListPanel().add( + new JLabel("" + c.getUsername() + " wrote " + (c.getPostedAt().equals(JUST_NOW) ? "" : "on ") + + c.getPostedAt() + " "), gbc); + gbc.gridy = lastPosition++; + + JTextArea commentArea = new JTextArea(c.getComment().replace("
", "\n")); + commentArea.setEditable(false); + commentArea.setFont(getSendButton().getFont()); + commentArea.setLineWrap(true); + commentArea.setWrapStyleWord(true); + // commentArea.setRequestFocusEnabled(false); + commentArea.setForeground(Color.gray); + // DefaultCaret caret = (DefaultCaret) commentArea.getCaret(); + // caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + getListPanel().add(commentArea, gbc); + gbc.gridy = lastPosition++; + + gbc.fill = GridBagConstraints.HORIZONTAL; + getListPanel().add(new JSeparator(), gbc); + return commentArea; + } +} diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java index 65b0bf90..4989a81f 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java @@ -40,12 +40,13 @@ import org.diylc.common.IPlugInPort; import org.diylc.common.ITask; import org.diylc.core.IView; import org.diylc.images.IconLoader; +import org.diylc.plugins.cloud.model.CommentEntity; import org.diylc.plugins.cloud.model.ProjectEntity; -import org.diylc.plugins.cloud.presenter.CloudException; import org.diylc.plugins.cloud.presenter.CloudPresenter; import org.diylc.plugins.cloud.presenter.PagingProvider; import org.diylc.swing.ISwingUI; import org.diylc.swing.gui.DialogFactory; +import org.diylc.swing.plugins.cloud.view.CommentDialog; import org.diylc.swing.plugins.file.FileFilterEnum; public class ResultsScrollPanel extends JScrollPane { @@ -192,12 +193,26 @@ public class ResultsScrollPanel extends JScrollPane { commentLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - try { - cloudUI.showMessage(cloudPresenter.GetComments(project.getId()).toString(), "Comments", IView.INFORMATION_MESSAGE); - } catch (CloudException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } + cloudUI.executeBackgroundTask(new ITask>() { + + @Override + public List doInBackground() throws Exception { + return cloudPresenter.getComments(project.getId()); + } + + @Override + public void failed(Exception e) { + cloudUI.showMessage("Could not open file. Detailed message is in the logs.", "Cloud Error", + IView.ERROR_MESSAGE); + } + + @Override + public void complete(List result) { + CommentDialog dialog = new CommentDialog(cloudUI, project, result, cloudPresenter); + dialog.setVisible(true); + } + + }); } }); @@ -262,7 +277,7 @@ public class ResultsScrollPanel extends JScrollPane { @Override public void failed(Exception e) { - mainUI.showMessage("Could not open file. Detailed message is in the logs", "Error", + mainUI.showMessage("Could not open file. Detailed message is in the logs.", "Error", ISwingUI.ERROR_MESSAGE); } }); @@ -271,7 +286,7 @@ public class ResultsScrollPanel extends JScrollPane { @Override public void failed(Exception e) { - cloudUI.showMessage("Could not save to file. Detailed message is in the logs", "Error", + cloudUI.showMessage("Could not save to file. Detailed message is in the logs.", "Error", ISwingUI.ERROR_MESSAGE); } }); @@ -388,8 +403,8 @@ public class ResultsScrollPanel extends JScrollPane { List newResults = get(); addData(newResults); } catch (Exception e) { - cloudUI.showMessage("Search failed! Detailed message is in the logs. Please report to the author.", - "Search Failed", IView.ERROR_MESSAGE); + cloudUI.showMessage("Search failed! Detailed message is in the logs.", "Search Failed", + IView.ERROR_MESSAGE); } } };