From 658a69a870d8f41927f899cc1f0ad44b3e3f2331 Mon Sep 17 00:00:00 2001 From: elroygohjy Date: Fri, 8 Oct 2021 12:16:48 +0800 Subject: [PATCH 1/4] Feat: Add Note Command, Add Note UI & Add Note Date Saving --- .../seedu/address/commons/util/DateUtil.java | 23 +++ src/main/java/seedu/address/logic/Logic.java | 9 + .../seedu/address/logic/LogicManager.java | 16 ++ .../address/logic/commands/CommandResult.java | 25 ++- .../address/logic/commands/EditCommand.java | 15 +- .../address/logic/commands/ExitCommand.java | 3 +- .../address/logic/commands/HelpCommand.java | 2 +- .../address/logic/commands/NoteCommand.java | 31 +-- .../logic/parser/AddCommandParser.java | 4 +- .../logic/parser/NoteCommandParser.java | 9 +- .../java/seedu/address/model/person/Note.java | 8 + .../seedu/address/model/person/NoteDate.java | 29 +++ .../seedu/address/model/person/Person.java | 12 +- .../address/model/util/SampleDataUtil.java | 14 +- .../address/storage/JsonAdaptedPerson.java | 13 +- .../java/seedu/address/ui/MainWindow.java | 24 ++- .../java/seedu/address/ui/NoteWindow.java | 184 ++++++++++++++++++ .../java/seedu/address/ui/PersonCard.java | 2 +- src/main/resources/view/NoteWindow.fxml | 42 ++++ .../duplicatePersonAddressBook.json | 4 +- .../typicalPersonsAddressBook.json | 7 + .../logic/commands/CommandResultTest.java | 10 +- .../logic/commands/ExitCommandTest.java | 2 +- .../logic/commands/HelpCommandTest.java | 2 +- .../logic/commands/NoteCommandTest.java | 133 ------------- .../logic/parser/AddressBookParserTest.java | 5 +- .../logic/parser/NoteCommandParserTest.java | 15 +- .../storage/JsonAdaptedPersonTest.java | 15 +- .../seedu/address/testutil/PersonBuilder.java | 6 +- 29 files changed, 447 insertions(+), 217 deletions(-) create mode 100644 src/main/java/seedu/address/commons/util/DateUtil.java create mode 100644 src/main/java/seedu/address/model/person/NoteDate.java create mode 100644 src/main/java/seedu/address/ui/NoteWindow.java create mode 100644 src/main/resources/view/NoteWindow.fxml delete mode 100644 src/test/java/seedu/address/logic/commands/NoteCommandTest.java diff --git a/src/main/java/seedu/address/commons/util/DateUtil.java b/src/main/java/seedu/address/commons/util/DateUtil.java new file mode 100644 index 00000000000..92c644361c1 --- /dev/null +++ b/src/main/java/seedu/address/commons/util/DateUtil.java @@ -0,0 +1,23 @@ +package seedu.address.commons.util; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + + + +/** + * A class for getting current Date time in (E, MMM dd yyyy HH:mm) format. + */ +public class DateUtil { + public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("E, MMM dd yyyy HH:mm"); + + /** + * Returns the String representation of current date and time. + * + * @return String representation of current date and time. + */ + public static String getCurrentDateTime() { + return TIME_FORMATTER.format(LocalDateTime.now()); + } + +} diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..b2ad0ed610f 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -23,6 +23,15 @@ public interface Logic { */ CommandResult execute(String commandText) throws CommandException, ParseException; + + /** + * Executes instruction to save note of the person. + * + * @param person The person with yet to edit notes. + * @param editedPerson The person with newly edited notes. + * @throws CommandException + */ + void executeSaveNote(Person person, Person editedPerson) throws CommandException; /** * Returns the AddressBook. * diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9d9c6d15bdc..db03fff81bb 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -54,6 +54,22 @@ public CommandResult execute(String commandText) throws CommandException, ParseE return commandResult; } + /** + * Executes command to save Note of Person. + * @param person The person with yet to edit notes. + * @param editedPerson The person with newly edited notes. + * @throws CommandException If an error occurs during command execution. + */ + public void executeSaveNote(Person person, Person editedPerson) throws CommandException { + model.setPerson(person, editedPerson); + try { + storage.saveAddressBook(model.getAddressBook()); + } catch (IOException ioe) { + throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); + } + } + + @Override public ReadOnlyAddressBook getAddressBook() { return model.getAddressBook(); diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 92f900b7916..b91f7a5b348 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -4,6 +4,10 @@ import java.util.Objects; +import seedu.address.model.person.Person; + + + /** * Represents the result of a command execution. */ @@ -17,13 +21,21 @@ public class CommandResult { /** The application should exit. */ private final boolean exit; + /** The note should be shown for the respective user. */ + private final boolean showNote; + + private final Person person; + + /** * Constructs a {@code CommandResult} with the specified fields. */ - public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { + public CommandResult(String feedbackToUser, boolean showHelp, boolean showNote, Person person, boolean exit) { this.feedbackToUser = requireNonNull(feedbackToUser); this.showHelp = showHelp; + this.showNote = showNote; this.exit = exit; + this.person = person; } /** @@ -31,7 +43,7 @@ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { * and other fields set to their default value. */ public CommandResult(String feedbackToUser) { - this(feedbackToUser, false, false); + this(feedbackToUser, false, false, null, false); } public String getFeedbackToUser() { @@ -42,10 +54,18 @@ public boolean isShowHelp() { return showHelp; } + public boolean isShowNote() { + return showNote; + } + public boolean isExit() { return exit; } + public Person person() { + return person; + } + @Override public boolean equals(Object other) { if (other == this) { @@ -60,6 +80,7 @@ public boolean equals(Object other) { CommandResult otherCommandResult = (CommandResult) other; return feedbackToUser.equals(otherCommandResult.feedbackToUser) && showHelp == otherCommandResult.showHelp + && showNote == otherCommandResult.showNote && exit == otherCommandResult.exit; } diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 6d55badb754..7793ce4851c 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -21,6 +21,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -96,8 +97,9 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); Note updatedNote = editPersonDescriptor.getNote().orElse(personToEdit.getNote()); + NoteDate updatedNoteDate = editPersonDescriptor.getNoteDate().orElse(personToEdit.getNoteDate()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedNote, updatedTags); + return new Person(updatedName, updatedPhone, updatedEmail, updatedNote, updatedNoteDate, updatedTags); } @Override @@ -128,6 +130,7 @@ public static class EditPersonDescriptor { private Email email; private Set tags; private Note note; + private NoteDate noteDate; public EditPersonDescriptor() {} @@ -141,6 +144,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setEmail(toCopy.email); setTags(toCopy.tags); setNote(toCopy.note); + setNoteDate(toCopy.noteDate); } /** @@ -177,11 +181,18 @@ public Optional getEmail() { public void setNote(Note note) { this.note = note; } - public Optional getNote() { return Optional.ofNullable(note); } + public void setNoteDate(NoteDate noteDate) { + this.noteDate = noteDate; + } + + public Optional getNoteDate() { + return Optional.ofNullable(noteDate); + } + /** * Sets {@code tags} to this object's {@code tags}. * A defensive copy of {@code tags} is used internally. diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index 3dd85a8ba90..8563eb77b4d 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -13,7 +13,8 @@ public class ExitCommand extends Command { @Override public CommandResult execute(Model model) { - return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); + return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, false, + null, true); } } diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index bf824f91bd0..e4c9626dbb1 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -16,6 +16,6 @@ public class HelpCommand extends Command { @Override public CommandResult execute(Model model) { - return new CommandResult(SHOWING_HELP_MESSAGE, true, false); + return new CommandResult(SHOWING_HELP_MESSAGE, true, false, null, false); } } diff --git a/src/main/java/seedu/address/logic/commands/NoteCommand.java b/src/main/java/seedu/address/logic/commands/NoteCommand.java index 40592cb5738..65b10653b33 100644 --- a/src/main/java/seedu/address/logic/commands/NoteCommand.java +++ b/src/main/java/seedu/address/logic/commands/NoteCommand.java @@ -1,8 +1,6 @@ package seedu.address.logic.commands; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; import java.util.List; @@ -10,7 +8,6 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Note; import seedu.address.model.person.Person; /** @@ -19,29 +16,23 @@ public class NoteCommand extends Command { public static final String COMMAND_WORD = "note"; - public static final String MESSAGE_ADD_NOTE_SUCCESS = "Added note to Person: %1$s"; + public static final String MESSAGE_ADD_NOTE_SUCCESS = "Opened note to Person: %1$s"; public static final String MESSAGE_DELETE_NOTE_SUCCESS = "Removed note from Person: %1$s"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the notes of the person identified " + "by the index number used in the last person listing. " + "Existing notes will be overwritten by the input.\n" + "Parameters: INDEX (must be a positive integer) " - + PREFIX_NOTE + "[NOTE]\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_NOTE + "Likes to swim."; + + "Example: " + COMMAND_WORD + " 1 "; private final Index index; - private final Note note; /** * @param index Index of the person in currently displayed person list to edit note for. - * @param note New note to be updated to. */ - public NoteCommand(Index index, Note note) { - requireAllNonNull(index, note); - + public NoteCommand(Index index) { + requireAllNonNull(index); this.index = index; - this.note = note; } @Override @@ -53,13 +44,7 @@ public CommandResult execute(Model model) throws CommandException { } Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = new Person( - personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), note, personToEdit.getTags()); - - model.setPerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - - return new CommandResult(generateSuccessMessage(editedPerson)); + return new CommandResult(generateSuccessMessage(personToEdit), false, true, personToEdit, false); } /** @@ -68,8 +53,7 @@ public CommandResult execute(Model model) throws CommandException { * {@code personToEdit}. */ private String generateSuccessMessage(Person personToEdit) { - String message = !note.value.isEmpty() ? MESSAGE_ADD_NOTE_SUCCESS : MESSAGE_DELETE_NOTE_SUCCESS; - return String.format(message, personToEdit); + return String.format(MESSAGE_ADD_NOTE_SUCCESS, personToEdit); } @Override @@ -84,7 +68,6 @@ public boolean equals(Object other) { } // state check NoteCommand e = (NoteCommand) other; - return index.equals(e.index) - && note.equals(e.note); + return index.equals(e.index); } } diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 302e2870c4a..57bdcdc6164 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -14,6 +14,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -46,9 +47,10 @@ public AddCommand parse(String args) throws ParseException { Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); Note note = new Note(""); + NoteDate noteDate = new NoteDate(); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, note, tagList); + Person person = new Person(name, phone, email, note, noteDate, tagList); return new AddCommand(person); } diff --git a/src/main/java/seedu/address/logic/parser/NoteCommandParser.java b/src/main/java/seedu/address/logic/parser/NoteCommandParser.java index ecb56312c30..4a27413678d 100644 --- a/src/main/java/seedu/address/logic/parser/NoteCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/NoteCommandParser.java @@ -2,13 +2,12 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.NoteCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Note; + public class NoteCommandParser implements Parser { @@ -20,8 +19,7 @@ public class NoteCommandParser implements Parser { */ public NoteCommand parse(String args) throws ParseException { requireNonNull(args); - ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, - PREFIX_NOTE); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args); Index index; try { @@ -31,8 +29,7 @@ public NoteCommand parse(String args) throws ParseException { NoteCommand.MESSAGE_USAGE), ive); } - String note = argMultimap.getValue(PREFIX_NOTE).orElse(""); - return new NoteCommand(index, new Note(note)); + return new NoteCommand(index); } } diff --git a/src/main/java/seedu/address/model/person/Note.java b/src/main/java/seedu/address/model/person/Note.java index 43f2d7b2caf..a1c83b61238 100644 --- a/src/main/java/seedu/address/model/person/Note.java +++ b/src/main/java/seedu/address/model/person/Note.java @@ -2,9 +2,15 @@ import static java.util.Objects.requireNonNull; +/** + * Represents a Person's note that is opened upon note command. + */ public class Note { + + /** content of note **/ public final String value; + /** * Constructor for a Note instance. * @@ -36,4 +42,6 @@ public int hashCode() { public String toString() { return value; } + + } diff --git a/src/main/java/seedu/address/model/person/NoteDate.java b/src/main/java/seedu/address/model/person/NoteDate.java new file mode 100644 index 00000000000..4a750be87ae --- /dev/null +++ b/src/main/java/seedu/address/model/person/NoteDate.java @@ -0,0 +1,29 @@ +package seedu.address.model.person; + +/** + * Represents Note's last saved date. + */ +public class NoteDate { + public static final String EMPTY = ""; + public final String value; + + /** + * Constructor for a empty NoteDate instance. + */ + public NoteDate() { + this.value = EMPTY; + } + /** + * Constructor for a NoteDate instance. + * + * @param value Value of the note. + */ + public NoteDate(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index 73c519503c3..bf825eeeb77 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -22,17 +22,19 @@ public class Person { // Data fields private final Note note; + private final NoteDate noteDate; private final Set tags = new HashSet<>(); /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Note note, Set tags) { + public Person(Name name, Phone phone, Email email, Note note, NoteDate noteDate, Set tags) { requireAllNonNull(name, phone, email, tags); this.name = name; this.phone = phone; this.email = email; this.note = note; + this.noteDate = noteDate; this.tags.addAll(tags); } @@ -52,6 +54,10 @@ public Note getNote() { return note; } + public NoteDate getNoteDate() { + return noteDate; + } + /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. @@ -108,8 +114,8 @@ public String toString() { .append(getPhone()) .append("; Email: ") .append(getEmail()) - .append("; Note: ") - .append(getNote()); + .append("; NoteDate: ") + .append(getNoteDate()); Set tags = getTags(); if (!tags.isEmpty()) { diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 828f52b4ed3..ee8e8cbdc52 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -9,6 +9,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -18,21 +19,22 @@ */ public class SampleDataUtil { public static final Note EMPTY_NOTE = new Note(""); + public static final NoteDate EMPTY_NOTE_DATE = new NoteDate(); public static Person[] getSamplePersons() { return new Person[]{ new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), - EMPTY_NOTE, getTagSet("friends")), + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("friends")), new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - EMPTY_NOTE, getTagSet("colleagues", "friends")), + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("colleagues", "friends")), new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - EMPTY_NOTE, getTagSet("neighbours")), + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("neighbours")), new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - EMPTY_NOTE, getTagSet("family")), + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("family")), new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - EMPTY_NOTE, getTagSet("classmates")), + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("classmates")), new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - EMPTY_NOTE, getTagSet("colleagues")) + EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("colleagues")) }; } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java index 72a78d50b19..d0eaa212443 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java @@ -13,6 +13,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -28,6 +29,7 @@ class JsonAdaptedPerson { private final String phone; private final String email; private final String note; + private final String noteDate; private final List tagged = new ArrayList<>(); /** @@ -36,11 +38,12 @@ class JsonAdaptedPerson { @JsonCreator public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone, @JsonProperty("email") String email, @JsonProperty("note") String note, - @JsonProperty("tagged") List tagged) { + @JsonProperty("noteDate") String noteDate, @JsonProperty("tagged") List tagged) { this.name = name; this.phone = phone; this.email = email; this.note = note; + this.noteDate = noteDate; if (tagged != null) { this.tagged.addAll(tagged); } @@ -54,6 +57,7 @@ public JsonAdaptedPerson(Person source) { phone = source.getPhone().value; email = source.getEmail().value; note = source.getNote().value; + noteDate = source.getNoteDate().value; tagged.addAll(source.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList())); @@ -97,10 +101,15 @@ public Person toModelType() throws IllegalValueException { if (note == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Note.class.getSimpleName())); } + if (noteDate == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + NoteDate.class.getSimpleName())); + } final Note modelNote = new Note(note); + final NoteDate modelNoteDate = new NoteDate(noteDate); final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelNote, modelTags); + return new Person(modelName, modelPhone, modelEmail, modelNote, modelNoteDate, modelTags); } } diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 54c2be3d6bc..ae6963d4384 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -16,6 +16,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.Person; /** * The Main Window. Provides the basic application layout containing @@ -35,6 +36,7 @@ public class MainWindow extends UiPart { private PersonListPanel personListPanel; private ResultDisplay resultDisplay; + @FXML private StackPane commandBoxPlaceholder; @@ -64,8 +66,8 @@ public MainWindow(Stage primaryStage, Logic logic) { setWindowDefaultSize(logic.getGuiSettings()); setAccelerators(); - helpWindow = new HelpWindow(); + } public Stage getPrimaryStage() { @@ -146,6 +148,20 @@ public void handleHelp() { helpWindow.focus(); } } + /** + * Opens the note window or focuses on it if it's already opened. + */ + @FXML + public void handleNote(Person person, Logic logic) { + NoteWindow noteWindow = new NoteWindow(person, logic); + if (!NoteWindow.OPENED_NOTE_WINDOWS.contains(noteWindow)) { + NoteWindow.OPENED_NOTE_WINDOWS.add(noteWindow); + noteWindow.show(); + } else { + int indexOfNoteWindow = NoteWindow.OPENED_NOTE_WINDOWS.indexOf(noteWindow); + NoteWindow.OPENED_NOTE_WINDOWS.get(indexOfNoteWindow).focus(); + } + } void show() { primaryStage.show(); @@ -160,6 +176,7 @@ private void handleExit() { (int) primaryStage.getX(), (int) primaryStage.getY()); logic.setGuiSettings(guiSettings); helpWindow.hide(); + NoteWindow.OPENED_NOTE_WINDOWS.forEach(NoteWindow::hide); primaryStage.hide(); } @@ -177,11 +194,12 @@ private CommandResult executeCommand(String commandText) throws CommandException CommandResult commandResult = logic.execute(commandText); logger.info("Result: " + commandResult.getFeedbackToUser()); resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser()); - if (commandResult.isShowHelp()) { handleHelp(); } - + if (commandResult.isShowNote()) { + handleNote(commandResult.person(), logic); + } if (commandResult.isExit()) { handleExit(); } diff --git a/src/main/java/seedu/address/ui/NoteWindow.java b/src/main/java/seedu/address/ui/NoteWindow.java new file mode 100644 index 00000000000..e1464dbb0d8 --- /dev/null +++ b/src/main/java/seedu/address/ui/NoteWindow.java @@ -0,0 +1,184 @@ +package seedu.address.ui; + +import java.util.ArrayList; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.TextArea; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyCodeCombination; +import javafx.scene.input.KeyCombination; +import javafx.scene.input.KeyCombination.Modifier; +import javafx.scene.input.KeyEvent; +import javafx.stage.Stage; +import seedu.address.commons.util.DateUtil; +import seedu.address.logic.Logic; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; +import seedu.address.model.person.Person; + + + +public class NoteWindow extends UiPart { + + protected static final ArrayList OPENED_NOTE_WINDOWS = new ArrayList<>(); + private static final String FXML = "NoteWindow.fxml"; + private static final Modifier CTRL = KeyCombination.SHORTCUT_DOWN; + private static final KeyCombination SAVE_KEY = new KeyCodeCombination(KeyCode.S, CTRL); + private static final KeyCombination EXIT_AND_SAVE_KEY = new KeyCodeCombination(KeyCode.Q, CTRL); + private static final KeyCombination EXIT_KEY = new KeyCodeCombination(KeyCode.W, CTRL); + private static final KeyCombination TIME_STAMP_KEY = new KeyCodeCombination(KeyCode.T, CTRL); + + @FXML + private TextArea noteTextArea; + + private final Person person; + + private final Logic logic; + + + /** + * Creates a new NoteWindow. + */ + public NoteWindow(Person person, Logic logic) { + super(FXML); + noteTextArea.setText(person.getNote().value); + this.person = person; + this.logic = logic; + getRoot().setTitle(person.getName().toString()); + } + + /** + * Show the noteWindow. + */ + public void show() { + getRoot().show(); + getRoot().centerOnScreen(); + } + + /** + * Returns true if the note window is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Hides the note window. + */ + public void hide() { + getRoot().hide(); + } + + /** + * Focuses on the note window. + */ + public void focus() { + getRoot().setIconified(false); + getRoot().requestFocus(); + } + + /** + * Saves the file + */ + @FXML + public void handleSave() throws CommandException { + String paragraph = noteTextArea.getText(); + Note editedNote = new Note(paragraph); + NoteDate newNoteDate = new NoteDate(DateUtil.getCurrentDateTime()); + Person editedPerson = new Person(person.getName(), person.getPhone(), person.getEmail(), + editedNote, newNoteDate, person.getTags()); + logic.executeSaveNote(person, editedPerson); + } + + + /** + * Exits the note window. + */ + @FXML + public void handleExit() { + getRoot().close(); + OPENED_NOTE_WINDOWS.remove(this); + } + /** + * Exits and saves the note window. + */ + @FXML + public void handleSaveAndExit() throws CommandException { + handleSave(); + handleExit(); + } + + /** + * Returns the index of first character of current line of the text cursor. + * @return index of current line + */ + private int getLineIndex() { + int noOfCharsTillCursor = noteTextArea.getCaretPosition(); + int wordIndex = 0; + ObservableList noteCharSequence = noteTextArea.getParagraphs(); + for (CharSequence charSequence : noteCharSequence) { + int noOfChars = charSequence.length() + 1; + if (wordIndex + noOfChars >= noOfCharsTillCursor) { + return wordIndex; + } + wordIndex += noOfChars; + } + return wordIndex; + } + + private void timeStampNote() { + int currentLine = getLineIndex(); + String noteBeforeLine = currentLine == 0 ? "" : noteTextArea.getText(0, currentLine); + System.out.println(noteBeforeLine); + String noteAfterLine = noteTextArea.getText(currentLine, noteTextArea.getLength()); + noteTextArea.setText(noteBeforeLine + System.lineSeparator() + DateUtil.getCurrentDateTime() + + System.lineSeparator() + noteAfterLine); + noteTextArea.selectPositionCaret(currentLine); + noteTextArea.deselect(); + } + + /** + * Reads user key event. Saves on pressing Ctrl + S. Exits on pressing Ctrl + W. Exits and saves on pressing + * Ctrl + Q. + * @param event User key Event + * @see seedu.address.logic.Logic#executeSaveNote(Person, Person) + */ + @FXML + public void handleOnKeyPressed(KeyEvent event) throws CommandException { + + if (SAVE_KEY.match(event)) { + handleSave(); + return; + } + if (EXIT_AND_SAVE_KEY.match(event)) { + handleSaveAndExit(); + return; + } + if (EXIT_KEY.match(event)) { + handleExit(); + return; + } + if (TIME_STAMP_KEY.match(event)) { + timeStampNote(); + } + } + + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof NoteWindow)) { + return false; + } + + NoteWindow otherPerson = (NoteWindow) other; + return otherPerson.person.equals(this.person); + + } + +} diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index f1a3abc39a1..6c84b829f71 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -51,7 +51,7 @@ public PersonCard(Person person, int displayedIndex) { name.setText(person.getName().fullName); phone.setText(person.getPhone().value); email.setText(person.getEmail().value); - note.setText(person.getNote().value); + note.setText(person.getNoteDate().value); person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); diff --git a/src/main/resources/view/NoteWindow.fxml b/src/main/resources/view/NoteWindow.fxml new file mode 100644 index 00000000000..0779f58fcb2 --- /dev/null +++ b/src/main/resources/view/NoteWindow.fxml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json index 35c5aba1a63..8036d991954 100644 --- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json @@ -4,11 +4,13 @@ "phone": "94351253", "email": "alice@example.com", "note" : "", + "noteDate" : "", "tagged": [ "friends" ] }, { "name": "Alice Pauline", "phone": "94351253", "email": "pauline@example.com", - "note" : "" + "note" : "", + "noteDate" : "" } ] } diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 3aef69669f4..c2b219d8c64 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -5,42 +5,49 @@ "phone" : "94351253", "email" : "alice@example.com", "note": "", + "noteDate": "", "tagged" : [ "friends" ] }, { "name" : "Benson Meier", "phone" : "98765432", "email" : "johnd@example.com", "note": "", + "noteDate": "", "tagged" : [ "owesMoney", "friends" ] }, { "name" : "Carl Kurz", "phone" : "95352563", "email" : "heinz@example.com", "note": "", + "noteDate": "", "tagged" : [ ] }, { "name" : "Daniel Meier", "phone" : "87652533", "email" : "cornelia@example.com", "note": "", + "noteDate": "", "tagged" : [ "friends" ] }, { "name" : "Elle Meyer", "phone" : "9482224", "email" : "werner@example.com", "note": "", + "noteDate": "", "tagged" : [ ] }, { "name" : "Fiona Kunz", "phone" : "9482427", "email" : "lydia@example.com", "note": "", + "noteDate": "", "tagged" : [ ] }, { "name" : "George Best", "phone" : "9482442", "email" : "anna@example.com", "note": "", + "noteDate": "", "tagged" : [ ] } ] } diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/address/logic/commands/CommandResultTest.java index 4c98057f96c..16c0f0e4868 100644 --- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java +++ b/src/test/java/seedu/address/logic/commands/CommandResultTest.java @@ -12,7 +12,7 @@ public void equals() { // same values -> returns true assertEquals(commandResult, new CommandResult("feedback")); - assertEquals(commandResult, new CommandResult("feedback", false, false)); + assertEquals(commandResult, new CommandResult("feedback", false, false, null, false)); // same object -> returns true assertEquals(commandResult, commandResult); @@ -27,10 +27,10 @@ public void equals() { assertNotEquals(commandResult, new CommandResult("different")); // different showHelp value -> returns false - assertNotEquals(commandResult, new CommandResult("feedback", true, false)); + assertNotEquals(commandResult, new CommandResult("feedback", true, false, null, false)); // different exit value -> returns false - assertNotEquals(commandResult, new CommandResult("feedback", false, true)); + assertNotEquals(commandResult, new CommandResult("feedback", false, false, null, true)); } @Test @@ -44,9 +44,9 @@ public void hashcode() { assertNotEquals(commandResult.hashCode(), new CommandResult("different").hashCode()); // different showHelp value -> returns different hashcode - assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", true, false).hashCode()); + assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", true, false, null, false).hashCode()); // different exit value -> returns different hashcode - assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", false, true).hashCode()); + assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", false, false, null, true).hashCode()); } } diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java index 39a16643eb9..ead227fdc34 100644 --- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java @@ -14,7 +14,7 @@ public class ExitCommandTest { @Test public void execute_exit_success() { - CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); + CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, false, null, true); assertCommandSuccess(new ExitCommand(), model, expectedCommandResult, expectedModel); } } diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java index b7628bedcc2..76a518aa735 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java @@ -14,7 +14,7 @@ public class HelpCommandTest { @Test public void execute_help_success() { - CommandResult expectedCommandResult = new CommandResult(SHOWING_HELP_MESSAGE, true, false); + CommandResult expectedCommandResult = new CommandResult(SHOWING_HELP_MESSAGE, true, false, null, false); assertCommandSuccess(new HelpCommand(), model, expectedCommandResult, expectedModel); } } diff --git a/src/test/java/seedu/address/logic/commands/NoteCommandTest.java b/src/test/java/seedu/address/logic/commands/NoteCommandTest.java deleted file mode 100644 index d1a37dc4544..00000000000 --- a/src/test/java/seedu/address/logic/commands/NoteCommandTest.java +++ /dev/null @@ -1,133 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NOTE_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NOTE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Note; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; - -public class NoteCommandTest { - private static final String NOTE_STUB = "Example note."; - - private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - - @Test - public void execute_addRemarkUnfilteredList_success() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(firstPerson).withNote(NOTE_STUB).build(); - - NoteCommand remarkCommand = new NoteCommand(INDEX_FIRST_PERSON, new Note(editedPerson.getNote().value)); - - String expectedMessage = String.format(NoteCommand.MESSAGE_ADD_NOTE_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(firstPerson, editedPerson); - - assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_deleteRemarkUnfilteredList_success() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(firstPerson).withNote("").build(); - - NoteCommand remarkCommand = new NoteCommand(INDEX_FIRST_PERSON, - new Note(editedPerson.getNote().toString())); - - String expectedMessage = String.format(NoteCommand.MESSAGE_DELETE_NOTE_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(firstPerson, editedPerson); - - assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_filteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased())) - .withNote(NOTE_STUB).build(); - - NoteCommand remarkCommand = new NoteCommand(INDEX_FIRST_PERSON, new Note(editedPerson.getNote().value)); - - String expectedMessage = String.format(NoteCommand.MESSAGE_ADD_NOTE_SUCCESS, editedPerson); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(firstPerson, editedPerson); - - assertCommandSuccess(remarkCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_invalidPersonIndexUnfilteredList_failure() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - NoteCommand remarkCommand = new NoteCommand(outOfBoundIndex, new Note(VALID_NOTE_BOB)); - - assertCommandFailure(remarkCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - /** - * Edit filtered list where index is larger than size of filtered list, - * but smaller than size of address book - */ - @Test - public void execute_invalidPersonIndexFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - Index outOfBoundIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); - - NoteCommand remarkCommand = new NoteCommand(outOfBoundIndex, new Note(VALID_NOTE_BOB)); - - assertCommandFailure(remarkCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void equals() { - final NoteCommand standardCommand = new NoteCommand(INDEX_FIRST_PERSON, - new Note(VALID_NOTE_AMY)); - - // same values -> returns true - NoteCommand commandWithSameValues = new NoteCommand(INDEX_FIRST_PERSON, - new Note(VALID_NOTE_AMY)); - assertEquals(standardCommand, commandWithSameValues); - - // same object -> returns true - assertEquals(standardCommand, standardCommand); - - // null -> returns false - assertNotNull(standardCommand); - - // different types -> returns false - assertNotEquals(standardCommand, new ClearCommand()); - - // different index -> returns false - assertNotEquals(standardCommand, new NoteCommand(INDEX_SECOND_PERSON, - new Note(VALID_NOTE_AMY))); - - // different remark -> returns false - assertNotEquals(standardCommand, new NoteCommand(INDEX_FIRST_PERSON, - new Note(VALID_NOTE_BOB))); - } -} diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 8e980219fd2..bb28d57b7a1 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; @@ -94,8 +93,8 @@ public void parseCommand_list() throws Exception { public void parseCommand_note() throws Exception { final Note note = new Note("Test note."); NoteCommand command = (NoteCommand) parser.parseCommand(NoteCommand.COMMAND_WORD + " " - + INDEX_FIRST_PERSON.getOneBased() + " " + PREFIX_NOTE + note.value); - assertEquals(new NoteCommand(INDEX_FIRST_PERSON, note), command); + + INDEX_FIRST_PERSON.getOneBased()); + assertEquals(new NoteCommand(INDEX_FIRST_PERSON), command); } @Test diff --git a/src/test/java/seedu/address/logic/parser/NoteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/NoteCommandParserTest.java index b747f9976fa..01b738eddcd 100644 --- a/src/test/java/seedu/address/logic/parser/NoteCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/NoteCommandParserTest.java @@ -1,14 +1,11 @@ package seedu.address.logic.parser; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import org.junit.jupiter.api.Test; -import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.NoteCommand; -import seedu.address.model.person.Note; public class NoteCommandParserTest { private final NoteCommandParser parser = new NoteCommandParser(); @@ -16,15 +13,7 @@ public class NoteCommandParserTest { @Test public void parse_indexSpecified_success() { - // have remark - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + " " + PREFIX_NOTE + nonEmptyNote; - NoteCommand expectedCommand = new NoteCommand(INDEX_FIRST_PERSON, new Note(nonEmptyNote)); - assertParseSuccess(parser, userInput, expectedCommand); - - // no remark - userInput = targetIndex.getOneBased() + " " + PREFIX_NOTE; - expectedCommand = new NoteCommand(INDEX_FIRST_PERSON, new Note("")); - assertParseSuccess(parser, userInput, expectedCommand); + NoteCommand expectedCommand = new NoteCommand(INDEX_FIRST_PERSON); + assertParseSuccess(parser, "1", expectedCommand); } } diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java index c4e7df6ec3b..6cdc61766ef 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java @@ -26,6 +26,7 @@ public class JsonAdaptedPersonTest { private static final String VALID_PHONE = BENSON.getPhone().toString(); private static final String VALID_EMAIL = BENSON.getEmail().toString(); private static final String VALID_NOTE = BENSON.getNote().toString(); + private static final String VALID_NOTE_DATE = BENSON.getNoteDate().toString(); private static final List VALID_TAGS = BENSON.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList()); @@ -39,7 +40,7 @@ public void toModelType_validPersonDetails_returnsPerson() throws Exception { @Test public void toModelType_invalidName_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = Name.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -47,7 +48,7 @@ public void toModelType_invalidName_throwsIllegalValueException() { @Test public void toModelType_nullName_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -55,7 +56,7 @@ public void toModelType_nullName_throwsIllegalValueException() { @Test public void toModelType_invalidPhone_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = Phone.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -63,7 +64,7 @@ public void toModelType_invalidPhone_throwsIllegalValueException() { @Test public void toModelType_nullPhone_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -71,7 +72,7 @@ public void toModelType_nullPhone_throwsIllegalValueException() { @Test public void toModelType_invalidEmail_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = Email.MESSAGE_CONSTRAINTS; assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -79,7 +80,7 @@ public void toModelType_invalidEmail_throwsIllegalValueException() { @Test public void toModelType_nullEmail_throwsIllegalValueException() { JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_NOTE, VALID_TAGS); + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_NOTE, VALID_NOTE_DATE, VALID_TAGS); String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); } @@ -89,7 +90,7 @@ public void toModelType_invalidTags_throwsIllegalValueException() { List invalidTags = new ArrayList<>(VALID_TAGS); invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_NOTE, invalidTags); + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_NOTE, VALID_NOTE_DATE, invalidTags); assertThrows(IllegalValueException.class, person::toModelType); } diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/seedu/address/testutil/PersonBuilder.java index 2928b40ff05..55ce2302703 100644 --- a/src/test/java/seedu/address/testutil/PersonBuilder.java +++ b/src/test/java/seedu/address/testutil/PersonBuilder.java @@ -6,6 +6,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; +import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -25,6 +26,7 @@ public class PersonBuilder { private Phone phone; private Email email; private Note note; + private NoteDate noteDate; private Set tags; /** @@ -35,6 +37,7 @@ public PersonBuilder() { phone = new Phone(DEFAULT_PHONE); email = new Email(DEFAULT_EMAIL); note = new Note(DEFAULT_NOTE); + noteDate = new NoteDate(); tags = new HashSet<>(); } @@ -46,6 +49,7 @@ public PersonBuilder(Person personToCopy) { phone = personToCopy.getPhone(); email = personToCopy.getEmail(); note = personToCopy.getNote(); + noteDate = personToCopy.getNoteDate(); tags = new HashSet<>(personToCopy.getTags()); } @@ -90,7 +94,7 @@ public PersonBuilder withNote(String note) { } public Person build() { - return new Person(name, phone, email, note, tags); + return new Person(name, phone, email, note, noteDate, tags); } } From 19dc223e2d9f6cc56cd0ebd5f1ae84a4a59fdbbf Mon Sep 17 00:00:00 2001 From: elroygohjy Date: Mon, 11 Oct 2021 19:59:04 +0800 Subject: [PATCH 2/4] Refactor: NoteDate & Fix: CLI output For Note Command --- .../address/logic/commands/EditCommand.java | 13 +-------- .../logic/parser/AddCommandParser.java | 4 +-- .../java/seedu/address/model/person/Note.java | 15 ++++++++-- .../seedu/address/model/person/NoteDate.java | 29 ------------------- .../seedu/address/model/person/Person.java | 21 ++++++++------ .../address/model/util/SampleDataUtil.java | 14 ++++----- .../address/storage/JsonAdaptedPerson.java | 9 +++--- .../java/seedu/address/ui/NoteWindow.java | 6 ++-- .../java/seedu/address/ui/PersonCard.java | 8 +++-- src/main/resources/view/PersonListCard.fxml | 2 +- .../logic/parser/AddressBookParserTest.java | 2 +- .../storage/JsonAdaptedPersonTest.java | 2 +- .../seedu/address/testutil/PersonBuilder.java | 12 ++++---- .../address/testutil/TypicalPersons.java | 4 +-- 14 files changed, 57 insertions(+), 84 deletions(-) delete mode 100644 src/main/java/seedu/address/model/person/NoteDate.java diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 7793ce4851c..6e444bffe00 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -97,9 +97,8 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); Note updatedNote = editPersonDescriptor.getNote().orElse(personToEdit.getNote()); - NoteDate updatedNoteDate = editPersonDescriptor.getNoteDate().orElse(personToEdit.getNoteDate()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedNote, updatedNoteDate, updatedTags); + return new Person(updatedName, updatedPhone, updatedEmail, updatedNote, updatedTags); } @Override @@ -130,7 +129,6 @@ public static class EditPersonDescriptor { private Email email; private Set tags; private Note note; - private NoteDate noteDate; public EditPersonDescriptor() {} @@ -144,7 +142,6 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setEmail(toCopy.email); setTags(toCopy.tags); setNote(toCopy.note); - setNoteDate(toCopy.noteDate); } /** @@ -185,14 +182,6 @@ public Optional getNote() { return Optional.ofNullable(note); } - public void setNoteDate(NoteDate noteDate) { - this.noteDate = noteDate; - } - - public Optional getNoteDate() { - return Optional.ofNullable(noteDate); - } - /** * Sets {@code tags} to this object's {@code tags}. * A defensive copy of {@code tags} is used internally. diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 57bdcdc6164..eb8ccf21b49 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -46,11 +46,11 @@ public AddCommand parse(String args) throws ParseException { Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); - Note note = new Note(""); + Note note = new Note("", ""); NoteDate noteDate = new NoteDate(); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, note, noteDate, tagList); + Person person = new Person(name, phone, email, note, tagList); return new AddCommand(person); } diff --git a/src/main/java/seedu/address/model/person/Note.java b/src/main/java/seedu/address/model/person/Note.java index a1c83b61238..8e74eb46f74 100644 --- a/src/main/java/seedu/address/model/person/Note.java +++ b/src/main/java/seedu/address/model/person/Note.java @@ -9,6 +9,7 @@ public class Note { /** content of note **/ public final String value; + public final String savedDate; /** @@ -16,9 +17,19 @@ public class Note { * * @param value Value of the note. */ - public Note(String value) { + public Note(String value, String savedDate) { requireNonNull(value); this.value = value; + this.savedDate = savedDate; + } + + /** + * Returns string representation of saved date. + * + * @return String representation of saved date + */ + public String getSavedDate() { + return savedDate; } @Override @@ -30,7 +41,7 @@ public boolean equals(Object other) { return false; } Note noteOther = (Note) other; - return value.equals(noteOther.value); // state check + return value.equals(noteOther.value) && savedDate.equals(noteOther.savedDate); // state check } @Override diff --git a/src/main/java/seedu/address/model/person/NoteDate.java b/src/main/java/seedu/address/model/person/NoteDate.java deleted file mode 100644 index 4a750be87ae..00000000000 --- a/src/main/java/seedu/address/model/person/NoteDate.java +++ /dev/null @@ -1,29 +0,0 @@ -package seedu.address.model.person; - -/** - * Represents Note's last saved date. - */ -public class NoteDate { - public static final String EMPTY = ""; - public final String value; - - /** - * Constructor for a empty NoteDate instance. - */ - public NoteDate() { - this.value = EMPTY; - } - /** - * Constructor for a NoteDate instance. - * - * @param value Value of the note. - */ - public NoteDate(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } -} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index bf825eeeb77..622bfc5bc0e 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -22,19 +22,17 @@ public class Person { // Data fields private final Note note; - private final NoteDate noteDate; private final Set tags = new HashSet<>(); /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Note note, NoteDate noteDate, Set tags) { + public Person(Name name, Phone phone, Email email, Note note, Set tags) { requireAllNonNull(name, phone, email, tags); this.name = name; this.phone = phone; this.email = email; this.note = note; - this.noteDate = noteDate; this.tags.addAll(tags); } @@ -53,11 +51,11 @@ public Email getEmail() { public Note getNote() { return note; } - - public NoteDate getNoteDate() { - return noteDate; + public String getNoteSavedDate() { + return note.getSavedDate(); } + /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. @@ -113,15 +111,20 @@ public String toString() { .append("; Phone: ") .append(getPhone()) .append("; Email: ") - .append(getEmail()) - .append("; NoteDate: ") - .append(getNoteDate()); + .append(getEmail()); + String noteSavedDate = note.getSavedDate(); + if (!noteSavedDate.isEmpty()) { + builder.append("; Last Edited: ") + .append(getNoteSavedDate()); + } Set tags = getTags(); + if (!tags.isEmpty()) { builder.append("; Tags: "); tags.forEach(builder::append); } + return builder.toString(); } diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index ee8e8cbdc52..cc132ea2775 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -18,23 +18,23 @@ * Contains utility methods for populating {@code AddressBook} with sample data. */ public class SampleDataUtil { - public static final Note EMPTY_NOTE = new Note(""); + public static final Note EMPTY_NOTE = new Note("", ""); public static final NoteDate EMPTY_NOTE_DATE = new NoteDate(); public static Person[] getSamplePersons() { return new Person[]{ new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("friends")), + EMPTY_NOTE, getTagSet("friends")), new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("colleagues", "friends")), + EMPTY_NOTE, getTagSet("colleagues", "friends")), new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("neighbours")), + EMPTY_NOTE, getTagSet("neighbours")), new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("family")), + EMPTY_NOTE, getTagSet("family")), new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("classmates")), + EMPTY_NOTE, getTagSet("classmates")), new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - EMPTY_NOTE, EMPTY_NOTE_DATE, getTagSet("colleagues")) + EMPTY_NOTE, getTagSet("colleagues")) }; } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java index d0eaa212443..2a82c380626 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java @@ -57,7 +57,7 @@ public JsonAdaptedPerson(Person source) { phone = source.getPhone().value; email = source.getEmail().value; note = source.getNote().value; - noteDate = source.getNoteDate().value; + noteDate = source.getNote().getSavedDate(); tagged.addAll(source.getTags().stream() .map(JsonAdaptedTag::new) .collect(Collectors.toList())); @@ -103,13 +103,12 @@ public Person toModelType() throws IllegalValueException { } if (noteDate == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, - NoteDate.class.getSimpleName())); + Note.class.getSimpleName())); } - final Note modelNote = new Note(note); - final NoteDate modelNoteDate = new NoteDate(noteDate); + final Note modelNote = new Note(note, noteDate); final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelNote, modelNoteDate, modelTags); + return new Person(modelName, modelPhone, modelEmail, modelNote, modelTags); } } diff --git a/src/main/java/seedu/address/ui/NoteWindow.java b/src/main/java/seedu/address/ui/NoteWindow.java index e1464dbb0d8..a450131f17e 100644 --- a/src/main/java/seedu/address/ui/NoteWindow.java +++ b/src/main/java/seedu/address/ui/NoteWindow.java @@ -15,7 +15,6 @@ import seedu.address.logic.Logic; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.person.Note; -import seedu.address.model.person.NoteDate; import seedu.address.model.person.Person; @@ -85,10 +84,9 @@ public void focus() { @FXML public void handleSave() throws CommandException { String paragraph = noteTextArea.getText(); - Note editedNote = new Note(paragraph); - NoteDate newNoteDate = new NoteDate(DateUtil.getCurrentDateTime()); + Note editedNote = new Note(paragraph, DateUtil.getCurrentDateTime()); Person editedPerson = new Person(person.getName(), person.getPhone(), person.getEmail(), - editedNote, newNoteDate, person.getTags()); + editedNote, person.getTags()); logic.executeSaveNote(person, editedPerson); } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 6c84b829f71..a00947fc831 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -37,7 +37,7 @@ public class PersonCard extends UiPart { @FXML private Label email; @FXML - private Label note; + private Label noteLastSaved; @FXML private FlowPane tags; @@ -51,7 +51,11 @@ public PersonCard(Person person, int displayedIndex) { name.setText(person.getName().fullName); phone.setText(person.getPhone().value); email.setText(person.getEmail().value); - note.setText(person.getNoteDate().value); + if (!person.getNoteSavedDate().isEmpty()) { + noteLastSaved.setText(person.getNoteSavedDate()); + } else { + noteLastSaved.setManaged(false); + } person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index f745ee0d676..025a416a538 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -30,7 +30,7 @@