diff --git a/src/main/java/seedu/address/logic/commands/AddCommentCommand.java b/src/main/java/seedu/address/logic/commands/AddCommentCommand.java new file mode 100644 index 00000000000..790a776b398 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/AddCommentCommand.java @@ -0,0 +1,89 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; +import seedu.address.model.project.Comment; +import seedu.address.model.project.Member; + +/** + * Adds a project to the DevPlanPro. + */ +public class AddCommentCommand extends Command { + + public static final String COMMAND_WORD = "add comment"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + " /from PERSON_NAME" + + " /in PROJECT_NAME"; + + public static final String MESSAGE_SUCCESS = "The comment %1$s has been added to the project %2$s."; + + public static final String MESSAGE_PROJECT_NOT_FOUND = "Project %1$s not found: " + + "Please make sure the project exists."; + + public static final String MESSAGE_MEMBER_NOT_FOUND = "Team member %1s not found: " + + "Please make sure the person exists."; + + private final Person commentProject; + + private final Member commentFrom; + + private Comment comment; + + /** + * Creates an AddCommand to add the specified {@code Person} + */ + public AddCommentCommand(Person project, Member member, String comment) { + requireNonNull(project); + this.commentProject = project; + this.commentFrom = member; + this.comment = new Comment(comment, member); + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + + if (!model.hasPerson(commentProject)) { + throw new CommandException(String.format(MESSAGE_PROJECT_NOT_FOUND, + Messages.format(commentProject))); + } + + Person foundProject = model.findPerson(commentProject.getName()); + + if (!foundProject.hasMember(commentFrom)) { + throw new CommandException(String.format(MESSAGE_MEMBER_NOT_FOUND, commentFrom)); + } + + Person project = model.findPerson(commentProject.getName()); + project.addComment(comment); + + return new CommandResult(String.format(MESSAGE_SUCCESS, comment, Messages.format(commentProject))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof AddCommentCommand)) { + return false; + } + + AddCommentCommand otherAddCommentCommand = (AddCommentCommand) other; + return commentProject.equals(otherAddCommentCommand.commentProject); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("Project", commentProject) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommentCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommentCommandParser.java new file mode 100644 index 00000000000..cba8b00722e --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/AddCommentCommandParser.java @@ -0,0 +1,52 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.logic.commands.AddCommentCommand; +import seedu.address.logic.commands.AddTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.Name; +import seedu.address.model.person.Person; +import seedu.address.model.project.Member; + + +/** + * Parses input arguments and creates a new AddProjectCommand object + */ +public class AddCommentCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the AddProjectCommand + * and returns an AddProjectCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public AddCommentCommand parse(String args) throws ParseException { + try { + if (!args.contains(" /from ")) { // Check if the input correctly uses "/to" + throw new ParseException(String.format( + MESSAGE_INVALID_COMMAND_FORMAT, + AddCommentCommand.MESSAGE_USAGE)); + } + if (!args.contains(" /in ")) { // Check if the input correctly uses "/to" + throw new ParseException(String.format( + MESSAGE_INVALID_COMMAND_FORMAT, + AddCommentCommand.MESSAGE_USAGE)); + } + String comment = args.split(" /from")[0]; + String memberAndProject = args.split(" /from ")[1]; + if ((comment.length() == 0) || (comment.length() == 0)) { + throw new ParseException("Please enter a comment"); + } + String memberName = memberAndProject.split(" /in")[0]; + Member member = new Member(memberName); + String projectName = memberAndProject.split(" /in")[1]; + Name name = ParserUtil.parseName(projectName); + Person project = new Person(name); + return new AddCommentCommand(project, member, comment); + } catch (ArrayIndexOutOfBoundsException e) { + throw new ParseException(String.format( + MESSAGE_INVALID_COMMAND_FORMAT, + AddTaskCommand.MESSAGE_USAGE)); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 3c5f69d5be0..1046f1012ff 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -8,6 +8,7 @@ import java.util.regex.Pattern; import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.commands.AddCommentCommand; import seedu.address.logic.commands.AddPersonCommand; import seedu.address.logic.commands.AddProjectCommand; import seedu.address.logic.commands.AddTaskCommand; @@ -71,6 +72,9 @@ public Command parseCommand(String userInput) throws ParseException { switch (commandWord) { + case AddCommentCommand.COMMAND_WORD: + return new AddCommentCommandParser().parse(arguments); + case AddPersonCommand.COMMAND_WORD: return new AddPersonCommandParser().parse(arguments); diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index 1dd68640704..5dafb895ac6 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -11,6 +11,7 @@ import java.util.stream.Collectors; import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.project.Comment; import seedu.address.model.project.Member; import seedu.address.model.project.Task; @@ -34,6 +35,8 @@ public class Person { private String category; + private List comments = new ArrayList<>(); + /** * Constructs a Person object with empty taskList */ @@ -231,6 +234,10 @@ public String getTeam() { .collect(Collectors.joining(", ")); } + public List getComments() { + return comments; + } + /** * Returns true if the Person has a task that is equal to the specified task */ @@ -256,6 +263,10 @@ public boolean hasMember(Member member) { return false; } + public void addComment(Comment comment) { + comments.add(comment); + } + /** * Returns a new person with new name but the same task (for edit person command) */ diff --git a/src/main/java/seedu/address/model/project/Comment.java b/src/main/java/seedu/address/model/project/Comment.java new file mode 100644 index 00000000000..3a1712b4003 --- /dev/null +++ b/src/main/java/seedu/address/model/project/Comment.java @@ -0,0 +1,35 @@ +package seedu.address.model.project; + +/** + * Comments within projects + * comments have a string field and a member field + */ +public class Comment { + private String comment; + private Member member; + + /** + * constructor for comment object + * @param comment comment in string format + * @param member person who made the comment + */ + public Comment(String comment, Member member) { + this.comment = comment; + this.member = member; + } + + /** + * @return project member who made the comment + */ + public Member getMember() { + return member; + } + + /** + * @return comment in string format + */ + @Override + public String toString() { + return comment; + } +} diff --git a/src/main/java/seedu/address/ui/CommentCard.java b/src/main/java/seedu/address/ui/CommentCard.java new file mode 100644 index 00000000000..5fb12c1278c --- /dev/null +++ b/src/main/java/seedu/address/ui/CommentCard.java @@ -0,0 +1,43 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import seedu.address.model.project.Comment; +import seedu.address.model.project.Member; + +/** + * Container for comments written within projects + */ +public class CommentCard extends UiPart { + private static final String FXML = "CommentListCard.fxml"; + + /** + * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. + * As a consequence, UI elements' variable names cannot be set to such keywords + * or an exception will be thrown by JavaFX during runtime. + * + * @see The issue on AddressBook level 4 + */ + + private final Member member; + + @FXML + private HBox cardPane; + @FXML + private Label name; + + @FXML + private Label comment; + + /** + * Creates a {@code PersonCode} with the given {@code Person} and index to display. + */ + public CommentCard(Comment commentAdd) { + super(FXML); + this.member = commentAdd.getMember(); + name.setText(member.getName().fullName); + comment.setText(commentAdd.toString()); + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index bfe45dd75b3..3fdb9eb6746 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -51,6 +51,9 @@ public class MainWindow extends UiPart { @FXML private StackPane currentProjectPanelPlaceholder; + @FXML + private StackPane addComment; + /** * Creates a {@code MainWindow} with the given {@code Stage} and {@code Logic}. */ diff --git a/src/main/java/seedu/address/ui/TaskListPanel.java b/src/main/java/seedu/address/ui/TaskListPanel.java index 5836fb53169..800a44139ed 100644 --- a/src/main/java/seedu/address/ui/TaskListPanel.java +++ b/src/main/java/seedu/address/ui/TaskListPanel.java @@ -1,11 +1,15 @@ package seedu.address.ui; +import java.util.logging.Logger; + import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; import seedu.address.model.person.Person; +import seedu.address.model.project.Comment; import seedu.address.model.project.Task; /** @@ -16,6 +20,8 @@ public class TaskListPanel extends UiPart { public final Person currentProject; + private final Logger logger = LogsCenter.getLogger(getClass()); + @FXML private Label showingProjectName; @FXML @@ -28,6 +34,11 @@ public class TaskListPanel extends UiPart { @FXML private Label team; + @FXML + private ListView comments; + + + /** * Creates a {@code PersonListPanel} with the given {@code ObservableList}. */ @@ -46,6 +57,11 @@ public TaskListPanel(Person currentProject) { doneTaskListView.getItems().addAll(currentProject.getDoneTasks()); doneTaskListView.setCellFactory(param -> new TaskListCell()); + + comments.getItems().clear(); + comments.getItems().addAll(currentProject.getComments()); + + comments.setCellFactory(param -> new CommentListCell()); } class TaskListCell extends ListCell { @@ -60,4 +76,16 @@ protected void updateItem(Task task, boolean empty) { } } + class CommentListCell extends ListCell { + @Override + protected void updateItem(Comment comment, boolean empty) { + super.updateItem(comment, empty); + if (empty || comment == null) { + setGraphic(null); + } else { + setGraphic(new CommentCard(comment).getRoot()); + } + } + } + } diff --git a/src/main/resources/view/CommentListCard.fxml b/src/main/resources/view/CommentListCard.fxml new file mode 100644 index 00000000000..02e43eb7567 --- /dev/null +++ b/src/main/resources/view/CommentListCard.fxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 951749a6c41..78bc7b78982 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -49,7 +49,7 @@ + minWidth="200" prefWidth="200" VBox.vgrow="ALWAYS"> @@ -57,7 +57,7 @@ + minWidth="800" prefWidth="800" VBox.vgrow="ALWAYS"> diff --git a/src/main/resources/view/TaskListPanel.fxml b/src/main/resources/view/TaskListPanel.fxml index 04c8f53aa86..b02df5bf1e1 100644 --- a/src/main/resources/view/TaskListPanel.fxml +++ b/src/main/resources/view/TaskListPanel.fxml @@ -57,5 +57,19 @@ + + + + + + + + +