From b623ea7f49d310cb7e26e56c371bee54dee56125 Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Mon, 28 Oct 2019 17:57:33 +0800 Subject: [PATCH 01/13] Add ViewCommandParser and ViewCommand; update Messages and Context --- .../seedu/address/commons/core/Messages.java | 5 +- .../address/logic/commands/DeleteCommand.java | 2 +- .../address/logic/commands/EditCommand.java | 2 +- .../address/logic/commands/ListCommand.java | 1 + .../address/logic/commands/ViewCommand.java | 84 +++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 + .../logic/parser/ListCommandParser.java | 1 + .../logic/parser/ViewCommandParser.java | 65 ++++++++++++++ .../java/seedu/address/model/Context.java | 4 +- .../seedu/address/logic/LogicManagerTest.java | 4 +- .../logic/commands/DeleteCommandTest.java | 4 +- .../logic/commands/EditCommandTest.java | 4 +- 12 files changed, 168 insertions(+), 12 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/ViewCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/ViewCommandParser.java diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e469..2faea6ca6c2 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -5,9 +5,10 @@ */ public class Messages { - public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command"; + public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command!"; public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s"; - public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid"; + public static final String MESSAGE_INVALID_ACTIVITY_DISPLAY_INDEX = "The activity index provided is invalid!"; + public static final String MESSAGE_INVALID_PERSON_DISPLAY_INDEX = "The person index provided is invalid!"; public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; } diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index 56c5d40b895..e6b081368b7 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -36,7 +36,7 @@ public CommandResult execute(Model model) throws CommandException { List lastShownList = model.getFilteredPersonList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 3805e2f8372..8f7cde38f1d 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -71,7 +71,7 @@ public CommandResult execute(Model model) throws CommandException { List lastShownList = model.getFilteredPersonList(); if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } Person personToEdit = lastShownList.get(index.getZeroBased()); diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index b18d257de33..017bfab46eb 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -38,6 +38,7 @@ public ListCommand(CommandSubType type) { public CommandResult execute(Model model) throws CommandException { requireNonNull(model); + // Contextual behaviour switch (this.type) { case CONTACT: model.setContext(Context.newListContactContext()); diff --git a/src/main/java/seedu/address/logic/commands/ViewCommand.java b/src/main/java/seedu/address/logic/commands/ViewCommand.java new file mode 100644 index 00000000000..b6ced8377f8 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/ViewCommand.java @@ -0,0 +1,84 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ACTIVITY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT; + +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.CommandSubType; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Context; +import seedu.address.model.ContextType; +import seedu.address.model.Model; +import seedu.address.model.activity.Activity; +import seedu.address.model.person.Person; + +/** + * Updates the GUI to list all entries of a specified type to the user. + */ +public class ViewCommand extends Command { + + public static final String COMMAND_WORD = "view"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Switches the current view to show the details of a contact or activity, " + + "identified by their display index (a positive integer) in the respective list.\n" + + "Parameters: " + PREFIX_CONTACT + "CONTACT_INDEX OR " + PREFIX_ACTIVITY + "ACTIVITY_INDEX\n" + + "Example: view " + PREFIX_CONTACT + "1"; + + public static final String MESSAGE_SUCCESS = "Showing the details of %s %s"; + public static final String MESSAGE_UNKNOWN_VIEW_TYPE = "View command has unknown type!"; + + private final Index targetIndex; + private final CommandSubType type; + + public ViewCommand(CommandSubType type, Index targetIndex) { + requireAllNonNull(type); + this.type = type; + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + + // Contextual behaviour + switch (this.type) { + case CONTACT: + List listedPersons = model.getFilteredPersonList(); + + if (targetIndex.getZeroBased() >= listedPersons.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); + } + + Person personToView = listedPersons.get(targetIndex.getZeroBased()); + model.setContext(new Context(personToView)); + + return new CommandResult(String.format(MESSAGE_SUCCESS, "contact"), ContextType.VIEW_CONTACT); + case ACTIVITY: + List listedActivities = model.getFilteredActivityList(); + + if (targetIndex.getZeroBased() >= listedActivities.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_ACTIVITY_DISPLAY_INDEX); + } + + Activity activityToView = listedActivities.get(targetIndex.getZeroBased()); + model.setContext(new Context(activityToView)); + + return new CommandResult(String.format(MESSAGE_SUCCESS, "activity"), ContextType.VIEW_ACTIVITY); + default: + throw new CommandException(MESSAGE_UNKNOWN_VIEW_TYPE); + } + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof ViewCommand // instanceof handles nulls + && type.equals(((ViewCommand) other).type)); // state check + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 87c90c6bd00..b9bc5c434b5 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -18,6 +18,7 @@ import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.InviteCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.ViewCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -80,6 +81,9 @@ public Command parseCommand(String userInput) throws ParseException { case ExpenseCommand.COMMAND_WORD: return new ExpenseCommandParser().parse(arguments); + case ViewCommand.COMMAND_WORD: + return new ViewCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/ListCommandParser.java b/src/main/java/seedu/address/logic/parser/ListCommandParser.java index 4b87a6f8a3f..60d28be81d2 100644 --- a/src/main/java/seedu/address/logic/parser/ListCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/ListCommandParser.java @@ -34,6 +34,7 @@ public ListCommand parse(String args) throws ParseException { if (argMultimap.getValue(PREFIX_ACTIVITY).isPresent()) { return new ListCommand(CommandSubType.ACTIVITY); } else { + assert argMultimap.getValue(PREFIX_CONTACT).isPresent(); return new ListCommand(CommandSubType.CONTACT); } } diff --git a/src/main/java/seedu/address/logic/parser/ViewCommandParser.java b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java new file mode 100644 index 00000000000..65bacaa7778 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java @@ -0,0 +1,65 @@ +package seedu.address.logic.parser; + +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_ACTIVITY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT; + +import java.util.stream.Stream; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.CommandSubType; +import seedu.address.logic.commands.ViewCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new {@code ViewCommand} object + */ +public class ViewCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of a {@code ViewCommand} + * and returns a {@code ViewCommand} object for execution. + * @throws ParseException if the user input does not conform to the expected format, + * or has missing compulsory arguments. + */ + public ViewCommand parse(String args) throws ParseException { + requireNonNull(args); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_CONTACT, PREFIX_ACTIVITY); + + if (!onePrefixPresent(argMultimap, PREFIX_CONTACT, PREFIX_ACTIVITY) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE)); + } + + CommandSubType subType; + String indexString; + + if (argMultimap.getValue(PREFIX_ACTIVITY).isPresent()) { + subType = CommandSubType.ACTIVITY; + indexString = argMultimap.getValue(PREFIX_ACTIVITY).get(); + } else { + assert argMultimap.getValue(PREFIX_CONTACT).isPresent(); + subType = CommandSubType.CONTACT; + indexString = argMultimap.getValue(PREFIX_CONTACT).get(); + } + + try { + Index index = ParserUtil.parseIndex(indexString); + return new ViewCommand(subType, index); + } catch (ParseException pe) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE), pe); + } + } + + /** + * Returns true if exactly one the prefixes contains a non-empty {@code Optional} value in the given + * {@code ArgumentMultimap}. + */ + private static boolean onePrefixPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes) + .filter(prefix -> argumentMultimap.getValue(prefix).isPresent()) + .count() == 1; + } +} diff --git a/src/main/java/seedu/address/model/Context.java b/src/main/java/seedu/address/model/Context.java index bf1d5264cc0..b909cdce3c1 100644 --- a/src/main/java/seedu/address/model/Context.java +++ b/src/main/java/seedu/address/model/Context.java @@ -18,7 +18,7 @@ public class Context { /** * Default constructor where context type is MAIN. */ - Context() { + public Context() { this.object = Optional.empty(); this.type = ContextType.MAIN; } @@ -40,7 +40,7 @@ public Context(Activity activity) { /** * Constructor for a VIEW_CONTACT context. */ - Context(Person person) { + public Context(Person person) { requireNonNull(person); object = Optional.ofNullable(person); type = ContextType.VIEW_CONTACT; diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 266d8f883e7..15d70fa635b 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -1,7 +1,7 @@ package seedu.address.logic; import static org.junit.jupiter.api.Assertions.assertEquals; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX; import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; @@ -70,7 +70,7 @@ public void execute_invalidCommandFormat_throwsParseException() { @Test public void execute_commandExecutionError_throwsCommandException() { String deleteCommand = "delete 9"; - assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + assertCommandException(deleteCommand, MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } @Test diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index 0142ecc5e4f..de2348f549a 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -49,7 +49,7 @@ public void execute_invalidIndexUnfilteredList_throwsCommandException() { Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } @Test @@ -80,7 +80,7 @@ public void execute_invalidIndexFilteredList_throwsCommandException() { DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } @Test diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index e0076b4abf0..310ea2ab0ef 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -133,7 +133,7 @@ public void execute_invalidPersonIndexUnfilteredList_failure() { EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build(); EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); - assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } /** @@ -150,7 +150,7 @@ public void execute_invalidPersonIndexFilteredList_failure() { EditCommand editCommand = new EditCommand(outOfBoundIndex, new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } @Test From 50e95f95cd1317f3e84aca9350cd123677bbd28b Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Mon, 28 Oct 2019 18:59:13 +0800 Subject: [PATCH 02/13] Amend CommandResult to pass full Context instead of just ContextType --- .../address/logic/commands/CommandResult.java | 13 ++++--- .../address/logic/commands/ListCommand.java | 15 +++++--- .../address/logic/commands/ViewCommand.java | 11 +++--- .../java/seedu/address/model/Context.java | 6 +++ .../address/model/activity/Activity.java | 1 + .../java/seedu/address/ui/MainWindow.java | 13 +++++-- .../logic/commands/CommandResultTest.java | 37 ++++++++++++------- .../logic/commands/ListCommandTest.java | 5 +-- .../java/seedu/address/model/ContextTest.java | 16 ++++++++ .../address/model/activity/ActivityTest.java | 10 ++++- 10 files changed, 91 insertions(+), 36 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 0e85c9f4b7d..0a37511e422 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -1,11 +1,12 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Objects; import java.util.Optional; -import seedu.address.model.ContextType; +import seedu.address.model.Context; /** * Represents the result of a command execution. @@ -20,8 +21,8 @@ public class CommandResult { /** The application should exit. */ private final boolean exit; - /** Type of updated context - empty if context was not changed by executing this command. */ - private final Optional newContext; + /** Updated application context - empty if context was not changed by executing this command. */ + private final Optional newContext; /** * Constructs a {@code CommandResult} with the specified fields, for commands that does not change @@ -40,8 +41,8 @@ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { * @param feedbackToUser {@code String} output from executing the command * @param newContext the new {@code ContextType} after executing the command */ - public CommandResult(String feedbackToUser, ContextType newContext) { - requireNonNull(newContext); + public CommandResult(String feedbackToUser, Context newContext) { + requireAllNonNull(feedbackToUser, newContext); this.feedbackToUser = requireNonNull(feedbackToUser); this.showHelp = false; this.exit = false; @@ -68,7 +69,7 @@ public boolean isExit() { return exit; } - public Optional getUpdatedContext() { + public Optional getUpdatedContext() { return newContext; } diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 017bfab46eb..58e91cef03d 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -8,7 +8,6 @@ import seedu.address.logic.CommandSubType; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Context; -import seedu.address.model.ContextType; import seedu.address.model.Model; /** @@ -41,13 +40,19 @@ public CommandResult execute(Model model) throws CommandException { // Contextual behaviour switch (this.type) { case CONTACT: - model.setContext(Context.newListContactContext()); + Context newContactContext = Context.newListContactContext(); + + model.setContext(newContactContext); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_ENTRIES); - return new CommandResult(String.format(MESSAGE_SUCCESS, "contacts"), ContextType.LIST_CONTACT); + + return new CommandResult(String.format(MESSAGE_SUCCESS, "contacts"), newContactContext); case ACTIVITY: - model.setContext(Context.newListActivityContext()); + Context newActivityContext = Context.newListActivityContext(); + + model.setContext(newActivityContext); model.updateFilteredActivityList(PREDICATE_SHOW_ALL_ENTRIES); - return new CommandResult(String.format(MESSAGE_SUCCESS, "activities"), ContextType.LIST_ACTIVITY); + + return new CommandResult(String.format(MESSAGE_SUCCESS, "activities"), newActivityContext); default: throw new CommandException(MESSAGE_UNKNOWN_LIST_TYPE); } diff --git a/src/main/java/seedu/address/logic/commands/ViewCommand.java b/src/main/java/seedu/address/logic/commands/ViewCommand.java index b6ced8377f8..8bbb7a804c1 100644 --- a/src/main/java/seedu/address/logic/commands/ViewCommand.java +++ b/src/main/java/seedu/address/logic/commands/ViewCommand.java @@ -12,7 +12,6 @@ import seedu.address.logic.CommandSubType; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Context; -import seedu.address.model.ContextType; import seedu.address.model.Model; import seedu.address.model.activity.Activity; import seedu.address.model.person.Person; @@ -56,9 +55,10 @@ public CommandResult execute(Model model) throws CommandException { } Person personToView = listedPersons.get(targetIndex.getZeroBased()); - model.setContext(new Context(personToView)); + Context newContactContext = new Context(personToView); + model.setContext(newContactContext); - return new CommandResult(String.format(MESSAGE_SUCCESS, "contact"), ContextType.VIEW_CONTACT); + return new CommandResult(String.format(MESSAGE_SUCCESS, "contact"), newContactContext); case ACTIVITY: List listedActivities = model.getFilteredActivityList(); @@ -67,9 +67,10 @@ public CommandResult execute(Model model) throws CommandException { } Activity activityToView = listedActivities.get(targetIndex.getZeroBased()); - model.setContext(new Context(activityToView)); + Context newActivityContext = new Context(activityToView); + model.setContext(newActivityContext); - return new CommandResult(String.format(MESSAGE_SUCCESS, "activity"), ContextType.VIEW_ACTIVITY); + return new CommandResult(String.format(MESSAGE_SUCCESS, "activity"), newActivityContext); default: throw new CommandException(MESSAGE_UNKNOWN_VIEW_TYPE); } diff --git a/src/main/java/seedu/address/model/Context.java b/src/main/java/seedu/address/model/Context.java index b909cdce3c1..f8380be7af9 100644 --- a/src/main/java/seedu/address/model/Context.java +++ b/src/main/java/seedu/address/model/Context.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +import java.util.Objects; import java.util.Optional; import seedu.address.model.activity.Activity; @@ -72,6 +73,11 @@ public Optional getContact() { return object.filter(x -> type == ContextType.VIEW_CONTACT).map(x->(Person) x); } + @Override + public int hashCode() { + return Objects.hash(type, object); + } + @Override public boolean equals(Object other) { if (this == other) { diff --git a/src/main/java/seedu/address/model/activity/Activity.java b/src/main/java/seedu/address/model/activity/Activity.java index 1c704ee3dd7..3ffcf863160 100644 --- a/src/main/java/seedu/address/model/activity/Activity.java +++ b/src/main/java/seedu/address/model/activity/Activity.java @@ -53,6 +53,7 @@ public Activity(int primaryKey, Title title, Integer ... ids) { this.title = title; invite(ids); } + /** Constructor for Activity. Sets primary key automatically. * @param title Title of the activity. diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 9412de56f7a..8f86c3671a7 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -1,5 +1,7 @@ package seedu.address.ui; +import static java.util.Objects.requireNonNull; + import java.util.Optional; import java.util.logging.Logger; @@ -12,6 +14,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.Context; import seedu.address.model.ContextType; import seedu.address.model.activity.Activity; import seedu.address.model.person.Person; @@ -141,10 +144,14 @@ private void handleExit() { * {@code ContextType}. * @param newContext the {@code ContextType} of the updated GUI view */ - private void contextSwitch(ContextType newContext) { + private void contextSwitch(Context newContext) { + requireNonNull(newContext); + contentContainer.getChildren().clear(); - switch (newContext) { + ContextType newContextType = newContext.getType(); + + switch (newContextType) { case LIST_ACTIVITY: contentContainer.getChildren().add(activityListPanel.getRoot()); break; @@ -183,7 +190,7 @@ private CommandResult executeCommand(String commandText) throws CommandException handleExit(); } - Optional newContext = commandResult.getUpdatedContext(); + Optional newContext = commandResult.getUpdatedContext(); if (newContext.isPresent()) { logger.info("Updated context: " + newContext.get().toString()); contextSwitch(newContext.get()); diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/address/logic/commands/CommandResultTest.java index 29e58c89c2e..631935e5f62 100644 --- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java +++ b/src/test/java/seedu/address/logic/commands/CommandResultTest.java @@ -7,7 +7,9 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.ContextType; +import seedu.address.model.Context; +import seedu.address.testutil.TypicalActivities; +import seedu.address.testutil.TypicalPersons; public class CommandResultTest { @Test @@ -36,16 +38,20 @@ public void equals() { // different exit value -> returns false assertFalse(commandResult.equals(new CommandResult("feedback", false, true))); - CommandResult contextualResult = new CommandResult("output", ContextType.LIST_ACTIVITY); + CommandResult contextualResult = new CommandResult("output", new Context(TypicalPersons.ALICE)); // identity -> returns true - assertTrue(contextualResult.equals(new CommandResult("output", ContextType.LIST_ACTIVITY))); + assertTrue(contextualResult.equals(new CommandResult("output", new Context(TypicalPersons.ALICE)))); - // empty context -> returns false - assertFalse(contextualResult.equals(commandResult)); + // empty Context -> returns false + assertFalse(contextualResult.equals(new CommandResult("output"))); - // non-empty but different context -> returns false - assertFalse(contextualResult.equals(new CommandResult("output", ContextType.VIEW_ACTIVITY))); + // different ContextType -> returns false + assertFalse(contextualResult.equals(new CommandResult("output", Context.newListContactContext()))); + assertFalse(contextualResult.equals(new CommandResult("output", new Context(TypicalActivities.BREAKFAST)))); + + // same ContextType but different value -> returns false + assertFalse(contextualResult.equals(new CommandResult("output", new Context(TypicalPersons.BOB)))); } @Test @@ -64,15 +70,20 @@ public void hashcode() { // different exit value -> returns different hashcode assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", false, true).hashCode()); - CommandResult contextualResult = new CommandResult("feedback", ContextType.VIEW_ACTIVITY); + CommandResult contextualResult = new CommandResult("feedback", new Context(TypicalActivities.BREAKFAST)); + int expectedHash = contextualResult.hashCode(); // identity -> returns same hashcode - assertEquals(contextualResult.hashCode(), - new CommandResult("feedback", ContextType.VIEW_ACTIVITY).hashCode()); + assertEquals(expectedHash, new CommandResult("feedback", new Context(TypicalActivities.BREAKFAST)).hashCode()); + + // empty Context -> returns false + assertNotEquals(expectedHash, new CommandResult("feedback").hashCode()); - // different context type -> returns different hashcode - assertNotEquals(contextualResult.hashCode(), - new CommandResult("feedback", ContextType.VIEW_CONTACT).hashCode()); + // different ContextType -> returns different hashcode + assertNotEquals(expectedHash, new CommandResult("feedback", Context.newListActivityContext()).hashCode()); + assertNotEquals(expectedHash, new CommandResult("feedback", new Context(TypicalPersons.ALICE)).hashCode()); + // same ContextType but different value -> returns false + assertNotEquals(expectedHash, new CommandResult("feedback", new Context(TypicalActivities.LUNCH)).hashCode()); } } diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index 5a425343304..c313c018c8b 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -12,7 +12,6 @@ import seedu.address.logic.CommandSubType; import seedu.address.model.Context; -import seedu.address.model.ContextType; import seedu.address.model.InternalState; import seedu.address.model.Model; import seedu.address.model.ModelManager; @@ -37,7 +36,7 @@ public void setUp() { model.getAddressBook(), new UserPrefs(), new InternalState(), getTypicalActivityBook()); expectedModel.setContext(Context.newListContactContext()); expectedMessage = String.format(ListCommand.MESSAGE_SUCCESS, "contacts"); - expectedResult = new CommandResult(expectedMessage, ContextType.LIST_CONTACT); + expectedResult = new CommandResult(expectedMessage, Context.newListContactContext()); } @Test @@ -62,7 +61,7 @@ public void execute_listIsFiltered_showsEverything() { public void execute_activityListIsFiltered_showsEverything() { expectedModel.setContext(Context.newListActivityContext()); expectedMessage = String.format(ListCommand.MESSAGE_SUCCESS, "activities"); - expectedResult = new CommandResult(expectedMessage, ContextType.LIST_ACTIVITY); + expectedResult = new CommandResult(expectedMessage, Context.newListActivityContext()); model.updateFilteredActivityList((activity) -> activity.getTitle().equals(new Title("Lunch"))); diff --git a/src/test/java/seedu/address/model/ContextTest.java b/src/test/java/seedu/address/model/ContextTest.java index 0ab88e6f682..fc7ee677344 100644 --- a/src/test/java/seedu/address/model/ContextTest.java +++ b/src/test/java/seedu/address/model/ContextTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; @@ -60,4 +61,19 @@ public void equals() { // same ContextType but different Person -> returns false assertFalse(viewPersonContext.equals(new Context(TypicalPersons.BENSON))); } + + @Test + public void hashcode() { + Context listContext = Context.newListActivityContext(); + Context viewContext = new Context(TypicalPersons.ALICE); + + // same Context values -> returns same hashcode + assertEquals(listContext.hashCode(), Context.newListActivityContext().hashCode()); + assertEquals(viewContext.hashCode(), new Context(TypicalPersons.ALICE).hashCode()); + + // different Context values -> returns different hashcodes + assertNotEquals(listContext.hashCode(), Context.newListContactContext().hashCode()); + assertNotEquals(viewContext.hashCode(), new Context(TypicalPersons.AMY).hashCode()); + assertNotEquals(listContext.hashCode(), viewContext.hashCode()); + } } diff --git a/src/test/java/seedu/address/model/activity/ActivityTest.java b/src/test/java/seedu/address/model/activity/ActivityTest.java index 87c51de4ef2..0344bf3b1a8 100644 --- a/src/test/java/seedu/address/model/activity/ActivityTest.java +++ b/src/test/java/seedu/address/model/activity/ActivityTest.java @@ -342,7 +342,15 @@ public void equals() { editedLunch = new ActivityBuilder(lunch).addPerson(TypicalPersons.ALICE).build(); assertFalse(lunch.equals(editedLunch)); - //TODO: Different expenses -> returns false; + // TODO: Different expenses -> returns false } + @Test + public void hashCode_sameActivityValues_hashCodeIsCorrect() { + Activity breakfast = TypicalActivities.BREAKFAST; + Activity breakfastCopy = new ActivityBuilder(breakfast).build(); + + // activities with same values -> returns true + assertEquals(breakfast.hashCode(), breakfastCopy.hashCode()); + } } From bbb11f485b76d1f5e6c3847dd5ffaa5130e5c006 Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Mon, 28 Oct 2019 19:31:50 +0800 Subject: [PATCH 03/13] Split generic ListPanel class into ActivityListPanel and PersonListPanel --- .../seedu/address/ui/ActivityListPanel.java | 46 +++++++++++++++++ src/main/java/seedu/address/ui/ListPanel.java | 49 ------------------- .../java/seedu/address/ui/MainWindow.java | 14 +++--- .../seedu/address/ui/PersonListPanel.java | 46 +++++++++++++++++ 4 files changed, 98 insertions(+), 57 deletions(-) create mode 100644 src/main/java/seedu/address/ui/ActivityListPanel.java delete mode 100644 src/main/java/seedu/address/ui/ListPanel.java create mode 100644 src/main/java/seedu/address/ui/PersonListPanel.java diff --git a/src/main/java/seedu/address/ui/ActivityListPanel.java b/src/main/java/seedu/address/ui/ActivityListPanel.java new file mode 100644 index 00000000000..6f34bc59e0a --- /dev/null +++ b/src/main/java/seedu/address/ui/ActivityListPanel.java @@ -0,0 +1,46 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +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.activity.Activity; + +/** + * Panel containing the list of activities. + */ +public class ActivityListPanel extends UiPart { + private static final String FXML = "ListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(ActivityListPanel.class); + + @FXML + private ListView listView; + + public ActivityListPanel(ObservableList activityList) { + super(FXML); + logger.info("Created ActivityListPanel to list activity entries."); + listView.setItems(activityList); + listView.setCellFactory(listView -> new ListViewCell()); + } + + /** + * Custom {@code ListCell} that displays the graphics of an {@code Activity} entry with an {@code ActivityCard}. + */ + class ListViewCell extends ListCell { + @Override + protected void updateItem(Activity activity, boolean empty) { + super.updateItem(activity, empty); + + if (empty || activity == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new ActivityCard(activity, getIndex() + 1).getRoot()); + } + } + } +} diff --git a/src/main/java/seedu/address/ui/ListPanel.java b/src/main/java/seedu/address/ui/ListPanel.java deleted file mode 100644 index a0d0bddd5c0..00000000000 --- a/src/main/java/seedu/address/ui/ListPanel.java +++ /dev/null @@ -1,49 +0,0 @@ -package seedu.address.ui; - -import java.util.logging.Logger; - -import javafx.collections.ObservableList; -import javafx.fxml.FXML; -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.activity.Activity; -import seedu.address.model.person.Person; - -/** - * Panel containing a list of entries to display. - */ -public class ListPanel extends UiPart { - private static final String FXML = "ListPanel.fxml"; - private final Logger logger = LogsCenter.getLogger(ListPanel.class); - - @FXML - private ListView listView; - - public ListPanel(ObservableList personList) { - super(FXML); - listView.setItems(personList); - listView.setCellFactory(listView -> new ListViewCell()); - } - - /** - * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. - */ - class ListViewCell extends ListCell { - @Override - protected void updateItem(U entry, boolean empty) { - super.updateItem(entry, empty); - - if (empty || entry == null) { - setGraphic(null); - setText(null); - } else if (entry instanceof Person) { - setGraphic(new PersonCard((Person) entry, getIndex() + 1).getRoot()); - } else if (entry instanceof Activity) { - setGraphic(new ActivityCard((Activity) entry, getIndex() + 1).getRoot()); - } - } - } - -} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 8f86c3671a7..406ab97fd29 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -16,8 +16,6 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Context; import seedu.address.model.ContextType; -import seedu.address.model.activity.Activity; -import seedu.address.model.person.Person; /** * The Main Window. Provides the basic application layout containing a status @@ -33,8 +31,8 @@ public class MainWindow extends UiPart { private Logic logic; // Independent Ui parts residing in this Ui container - private ListPanel personListPanel; - private ListPanel activityListPanel; + private PersonListPanel personListPanel; + private ActivityListPanel activityListPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; @@ -83,8 +81,8 @@ public Stage getPrimaryStage() { * Fills up all the containers of this window. */ void fillInnerParts() { - personListPanel = new ListPanel(logic.getFilteredPersonList()); - activityListPanel = new ListPanel(logic.getFilteredActivityList()); + personListPanel = new PersonListPanel(logic.getFilteredPersonList()); + activityListPanel = new ActivityListPanel(logic.getFilteredActivityList()); // Show contacts by default contentContainer.getChildren().add(personListPanel.getRoot()); @@ -163,11 +161,11 @@ private void contextSwitch(Context newContext) { } } - public ListPanel getPersonListPanel() { + public PersonListPanel getPersonListPanel() { return personListPanel; } - public ListPanel getActivityListPanel() { + public ActivityListPanel getActivityListPanel() { return activityListPanel; } diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java new file mode 100644 index 00000000000..f96dd6542c4 --- /dev/null +++ b/src/main/java/seedu/address/ui/PersonListPanel.java @@ -0,0 +1,46 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +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; + +/** + * Panel containing the list of persons. + */ +public class PersonListPanel extends UiPart { + private static final String FXML = "ListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); + + @FXML + private ListView listView; + + public PersonListPanel(ObservableList personList) { + super(FXML); + logger.info("Created PersonListPanel to list person entries."); + listView.setItems(personList); + listView.setCellFactory(listView -> new ListViewCell()); + } + + /** + * Custom {@code ListCell} that displays the graphics of a {@code Person} entry with a {@code PersonCard}. + */ + class ListViewCell extends ListCell { + @Override + protected void updateItem(Person person, boolean empty) { + super.updateItem(person, empty); + + if (empty || person == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new PersonCard(person, getIndex() + 1).getRoot()); + } + } + } +} From 796348facf2cd13a20038c373efaf9dfad5b006c Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Mon, 28 Oct 2019 20:05:10 +0800 Subject: [PATCH 04/13] Add tests for ViewCommandParser; rename static Indexes in TypicalIndexes --- .../logic/commands/CommandTestUtil.java | 2 +- .../logic/commands/DeleteCommandTest.java | 24 +++--- .../logic/commands/EditCommandTest.java | 39 +++++----- .../logic/commands/ListCommandTest.java | 4 +- .../logic/parser/AddressBookParserTest.java | 10 +-- .../logic/parser/DeleteCommandParserTest.java | 4 +- .../logic/parser/EditCommandParserTest.java | 18 ++--- .../logic/parser/ListCommandParserTest.java | 6 +- .../address/logic/parser/ParserUtilTest.java | 6 +- .../logic/parser/ViewCommandParserTest.java | 77 +++++++++++++++++++ .../address/testutil/TypicalIndexes.java | 6 +- 11 files changed, 136 insertions(+), 60 deletions(-) create mode 100644 src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index c7feec96d9f..a6e26ff6dba 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -129,6 +129,7 @@ public static void assertCommandFailure(Command command, Model actualModel, Stri assertEquals(expectedAddressBook, actualModel.getAddressBook()); assertEquals(expectedFilteredList, actualModel.getFilteredPersonList()); } + /** * Updates {@code model}'s filtered list to show only the person at the given {@code targetIndex} in the * {@code model}'s address book. @@ -142,5 +143,4 @@ public static void showPersonAtIndex(Model model, Index targetIndex) { assertEquals(1, model.getFilteredPersonList().size()); } - } diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index de2348f549a..13f6dd2cdb1 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -5,8 +5,8 @@ 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.TypicalIndexes.INDEX_FIRST; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import org.junit.jupiter.api.Test; @@ -31,8 +31,8 @@ public class DeleteCommandTest { @Test public void execute_validIndexUnfilteredList_success() { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); + Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST.getZeroBased()); + DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST); String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); @@ -54,10 +54,10 @@ public void execute_invalidIndexUnfilteredList_throwsCommandException() { @Test public void execute_validIndexFilteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, INDEX_FIRST); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); + Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST.getZeroBased()); + DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST); String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); @@ -72,9 +72,9 @@ public void execute_validIndexFilteredList_success() { @Test public void execute_invalidIndexFilteredList_throwsCommandException() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, INDEX_FIRST); - Index outOfBoundIndex = INDEX_SECOND_PERSON; + Index outOfBoundIndex = INDEX_SECOND; // ensures that outOfBoundIndex is still in bounds of address book list assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); @@ -85,14 +85,14 @@ public void execute_invalidIndexFilteredList_throwsCommandException() { @Test public void equals() { - DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON); - DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON); + DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST); + DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND); // same object -> returns true assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); // same values -> returns true - DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON); + DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST); assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); // different types -> returns false diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 310ea2ab0ef..2d37f9e5fa6 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -10,8 +10,8 @@ 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.TypicalIndexes.INDEX_FIRST; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import org.junit.jupiter.api.Test; @@ -41,7 +41,7 @@ public class EditCommandTest { public void execute_allFieldsSpecifiedUnfilteredList_success() { Person editedPerson = new PersonBuilder().build(); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor); + EditCommand editCommand = new EditCommand(INDEX_FIRST, descriptor); String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); @@ -77,8 +77,8 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() { @Test public void execute_noFieldSpecifiedUnfilteredList_success() { - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor()); - Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + EditCommand editCommand = new EditCommand(INDEX_FIRST, new EditPersonDescriptor()); + Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST.getZeroBased()); String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); @@ -90,11 +90,11 @@ public void execute_noFieldSpecifiedUnfilteredList_success() { @Test public void execute_filteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, INDEX_FIRST); - Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST.getZeroBased()); Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, + EditCommand editCommand = new EditCommand(INDEX_FIRST, new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); @@ -108,20 +108,20 @@ public void execute_filteredList_success() { @Test public void execute_duplicatePersonUnfilteredList_failure() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST.getZeroBased()); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor); + EditCommand editCommand = new EditCommand(INDEX_SECOND, descriptor); assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); } @Test public void execute_duplicatePersonFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, INDEX_FIRST); // edit person in filtered list into a duplicate in address book - Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, + Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND.getZeroBased()); + EditCommand editCommand = new EditCommand(INDEX_FIRST, new EditPersonDescriptorBuilder(personInList).build()); assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); @@ -142,8 +142,8 @@ public void execute_invalidPersonIndexUnfilteredList_failure() { */ @Test public void execute_invalidPersonIndexFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - Index outOfBoundIndex = INDEX_SECOND_PERSON; + showPersonAtIndex(model, INDEX_FIRST); + Index outOfBoundIndex = INDEX_SECOND; // ensures that outOfBoundIndex is still in bounds of address book list assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); @@ -155,11 +155,11 @@ public void execute_invalidPersonIndexFilteredList_failure() { @Test public void equals() { - final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY); + final EditCommand standardCommand = new EditCommand(INDEX_FIRST, DESC_AMY); // same values -> returns true EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY); - EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor); + EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST, copyDescriptor); assertTrue(standardCommand.equals(commandWithSameValues)); // same object -> returns true @@ -172,10 +172,9 @@ public void equals() { assertFalse(standardCommand.equals(new ClearCommand())); // different index -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY))); + assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND, DESC_AMY))); // different descriptor -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB))); + assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST, DESC_BOB))); } - } diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index c313c018c8b..e7503f58a22 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -4,7 +4,7 @@ import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalActivities.getTypicalActivityBook; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import org.junit.jupiter.api.BeforeEach; @@ -52,7 +52,7 @@ public void execute_listIsNotFiltered_showsSameList() { @Test public void execute_listIsFiltered_showsEverything() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, INDEX_FIRST); assertCommandSuccess(new ListCommand(CommandSubType.CONTACT), model, expectedResult, expectedModel); } diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index 5ae0fdd098c..830c5133c7a 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -5,7 +5,7 @@ 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.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; import java.util.Arrays; import java.util.List; @@ -48,8 +48,8 @@ public void parseCommand_clear() throws Exception { @Test public void parseCommand_delete() throws Exception { DeleteCommand command = (DeleteCommand) parser.parseCommand( - DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command); + DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST.getOneBased()); + assertEquals(new DeleteCommand(INDEX_FIRST), command); } @Test @@ -57,8 +57,8 @@ public void parseCommand_edit() throws Exception { Person person = new PersonBuilder().build(); EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build(); EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " " - + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor)); - assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command); + + INDEX_FIRST.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor)); + assertEquals(new EditCommand(INDEX_FIRST, descriptor), command); } @Test diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java index 27eaec84450..75763b1a46a 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java @@ -3,7 +3,7 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; import org.junit.jupiter.api.Test; @@ -22,7 +22,7 @@ public class DeleteCommandParserTest { @Test public void parse_validArgs_returnsDeleteCommand() { - assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON)); + assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST)); } @Test diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index 2ff31522486..a79956ddea3 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -27,9 +27,9 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND; +import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD; import org.junit.jupiter.api.Test; @@ -107,7 +107,7 @@ public void parse_invalidValue_failure() { @Test public void parse_allFieldsSpecified_success() { - Index targetIndex = INDEX_SECOND_PERSON; + Index targetIndex = INDEX_SECOND; String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND; @@ -121,7 +121,7 @@ public void parse_allFieldsSpecified_success() { @Test public void parse_someFieldsSpecified_success() { - Index targetIndex = INDEX_FIRST_PERSON; + Index targetIndex = INDEX_FIRST; String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY; EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB) @@ -134,7 +134,7 @@ public void parse_someFieldsSpecified_success() { @Test public void parse_oneFieldSpecified_success() { // name - Index targetIndex = INDEX_THIRD_PERSON; + Index targetIndex = INDEX_THIRD; String userInput = targetIndex.getOneBased() + NAME_DESC_AMY; EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build(); EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); @@ -167,7 +167,7 @@ public void parse_oneFieldSpecified_success() { @Test public void parse_multipleRepeatedFields_acceptsLast() { - Index targetIndex = INDEX_FIRST_PERSON; + Index targetIndex = INDEX_FIRST; String userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND; @@ -183,7 +183,7 @@ public void parse_multipleRepeatedFields_acceptsLast() { @Test public void parse_invalidValueFollowedByValidValue_success() { // no other valid values specified - Index targetIndex = INDEX_FIRST_PERSON; + Index targetIndex = INDEX_FIRST; String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB; EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB).build(); EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); @@ -200,7 +200,7 @@ public void parse_invalidValueFollowedByValidValue_success() { @Test public void parse_resetTags_success() { - Index targetIndex = INDEX_THIRD_PERSON; + Index targetIndex = INDEX_THIRD; String userInput = targetIndex.getOneBased() + TAG_EMPTY; EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build(); diff --git a/src/test/java/seedu/address/logic/parser/ListCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ListCommandParserTest.java index 0fe3699110d..b28e1e26abe 100644 --- a/src/test/java/seedu/address/logic/parser/ListCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/ListCommandParserTest.java @@ -26,13 +26,13 @@ public void parse_listTypeMissing_failure() { assertParseFailure(parser, "", String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); // All irrelevant fields - assertParseFailure(parser, " " + PREFIX_TITLE + VALID_ACTIVITY_TITLE + NAME_DESC_AMY, + assertParseFailure(parser, " " + PREFIX_TITLE + VALID_ACTIVITY_TITLE + " " + NAME_DESC_AMY, String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); } @Test public void parse_bothListTypesPresent_failure() { - // Both type fields c/ and a/ + // Both type fields c/ and a/ present assertParseFailure(parser, " " + PREFIX_CONTACT + " " + PREFIX_ACTIVITY, String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); } @@ -55,7 +55,7 @@ public void parse_preamblePresent_failure() { } @Test - public void parse_oneListSubTypeWithArg_successWithArgIgnored() { + public void parse_oneListTypeWithArg_successWithArgIgnored() { // Type field a/ with non-empty arg value assertParseSuccess(parser, " " + PREFIX_ACTIVITY + VALID_PHONE_AMY, new ListCommand(CommandSubType.ACTIVITY)); diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index f47116675b2..6bccbef7776 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; import java.util.Arrays; import java.util.Collections; @@ -55,10 +55,10 @@ public void parseIndex_outOfRangeInput_throwsParseException() { @Test public void parseIndex_validInput_success() throws Exception { // No whitespaces - assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex("1")); + assertEquals(INDEX_FIRST, ParserUtil.parseIndex("1")); // Leading and trailing whitespaces - assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 ")); + assertEquals(INDEX_FIRST, ParserUtil.parseIndex(" 1 ")); } @Test diff --git a/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java new file mode 100644 index 00000000000..836208ad1c5 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java @@ -0,0 +1,77 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.commands.CommandTestUtil.PARTICIPANT_DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.VALID_ACTIVITY_TITLE; +import static seedu.address.logic.commands.CommandTestUtil.VALID_AMOUNT_DESC; +import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; +import static seedu.address.logic.commands.ViewCommand.MESSAGE_USAGE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ACTIVITY; +import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT; + +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.CommandSubType; +import seedu.address.logic.commands.ViewCommand; +import seedu.address.testutil.TypicalIndexes; + +public class ViewCommandParserTest { + private ViewCommandParser parser = new ViewCommandParser(); + + @Test + public void parse_viewTypeMissing_failure() { + // Empty command + assertParseFailure(parser, "", String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + + // All irrelevant fields + assertParseFailure(parser, VALID_AMOUNT_DESC + " " + PARTICIPANT_DESC_AMY, + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + } + + @Test + public void parse_bothViewTypesPresent_failure() { + // Both type fields c/ and a/ present + assertParseFailure(parser, " " + PREFIX_CONTACT + "20 " + PREFIX_ACTIVITY + "40", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + } + + @Test + public void parse_oneViewTypeWithoutValidArg_failure() { + // Type field c/ with non-empty arg value + assertParseFailure(parser, " " + PREFIX_CONTACT, + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + + // Type field a/ with string as arg value + assertParseFailure(parser, " " + PREFIX_ACTIVITY + VALID_ACTIVITY_TITLE, + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + + // Type field c/ with non-positive integer as arg value + assertParseFailure(parser, " " + PREFIX_CONTACT + "0", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + } + + @Test + public void parse_oneViewTypePresentWithValidArg_success() { + // Only type field c/ + assertParseSuccess(parser, " " + PREFIX_ACTIVITY + "3", + new ViewCommand(CommandSubType.ACTIVITY, TypicalIndexes.INDEX_THIRD)); + + // Multiple of type field c/ + assertParseSuccess(parser, " " + PREFIX_CONTACT + "0 " + PREFIX_CONTACT + "2 " + PREFIX_CONTACT + "1", + new ViewCommand(CommandSubType.CONTACT, TypicalIndexes.INDEX_FIRST)); + + // Multiple of type field c/ - last arg is valid + assertParseSuccess(parser, " " + PREFIX_ACTIVITY + VALID_ACTIVITY_TITLE + " " + PREFIX_ACTIVITY + "2", + new ViewCommand(CommandSubType.ACTIVITY, TypicalIndexes.INDEX_SECOND)); + } + + @Test + public void parse_preamblePresent_failure() { + // Irrelevant field (preamble) followed by type field + assertParseFailure(parser, VALID_PHONE_AMY + " " + PREFIX_CONTACT + "2103", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, MESSAGE_USAGE)); + } +} diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java index 1e613937657..134e60a4c20 100644 --- a/src/test/java/seedu/address/testutil/TypicalIndexes.java +++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java @@ -6,7 +6,7 @@ * A utility class containing a list of {@code Index} objects to be used in tests. */ public class TypicalIndexes { - public static final Index INDEX_FIRST_PERSON = Index.fromOneBased(1); - public static final Index INDEX_SECOND_PERSON = Index.fromOneBased(2); - public static final Index INDEX_THIRD_PERSON = Index.fromOneBased(3); + public static final Index INDEX_FIRST = Index.fromOneBased(1); + public static final Index INDEX_SECOND = Index.fromOneBased(2); + public static final Index INDEX_THIRD = Index.fromOneBased(3); } From eb21038ffb0dee17e940c763a619aaac24268b5d Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Tue, 29 Oct 2019 00:01:29 +0800 Subject: [PATCH 05/13] Add equals method and tests for ViewCommand; update ListCommand tests --- .../address/logic/commands/CommandResult.java | 1 - .../address/logic/commands/ViewCommand.java | 29 ++-- .../logic/commands/DeleteCommandTest.java | 3 +- .../logic/commands/EditCommandTest.java | 2 +- .../logic/commands/ListCommandTest.java | 20 +++ .../logic/commands/ViewCommandTest.java | 130 ++++++++++++++++++ .../address/testutil/TypicalIndexes.java | 2 + 7 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/ViewCommandTest.java diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 0a37511e422..205a50f6ed9 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -95,5 +95,4 @@ public boolean equals(Object other) { public int hashCode() { return Objects.hash(feedbackToUser, showHelp, exit, newContext); } - } diff --git a/src/main/java/seedu/address/logic/commands/ViewCommand.java b/src/main/java/seedu/address/logic/commands/ViewCommand.java index 8bbb7a804c1..5568b0c4c7d 100644 --- a/src/main/java/seedu/address/logic/commands/ViewCommand.java +++ b/src/main/java/seedu/address/logic/commands/ViewCommand.java @@ -36,7 +36,7 @@ public class ViewCommand extends Command { private final CommandSubType type; public ViewCommand(CommandSubType type, Index targetIndex) { - requireAllNonNull(type); + requireAllNonNull(type, targetIndex); this.type = type; this.targetIndex = targetIndex; } @@ -50,7 +50,7 @@ public CommandResult execute(Model model) throws CommandException { case CONTACT: List listedPersons = model.getFilteredPersonList(); - if (targetIndex.getZeroBased() >= listedPersons.size()) { + if (targetIndex.getOneBased() > listedPersons.size()) { throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); } @@ -58,11 +58,12 @@ public CommandResult execute(Model model) throws CommandException { Context newContactContext = new Context(personToView); model.setContext(newContactContext); - return new CommandResult(String.format(MESSAGE_SUCCESS, "contact"), newContactContext); + return new CommandResult(String.format(MESSAGE_SUCCESS, "contact", personToView.getName()), + newContactContext); case ACTIVITY: List listedActivities = model.getFilteredActivityList(); - if (targetIndex.getZeroBased() >= listedActivities.size()) { + if (targetIndex.getOneBased() > listedActivities.size()) { throw new CommandException(Messages.MESSAGE_INVALID_ACTIVITY_DISPLAY_INDEX); } @@ -70,7 +71,8 @@ public CommandResult execute(Model model) throws CommandException { Context newActivityContext = new Context(activityToView); model.setContext(newActivityContext); - return new CommandResult(String.format(MESSAGE_SUCCESS, "activity"), newActivityContext); + return new CommandResult(String.format(MESSAGE_SUCCESS, "activity", activityToView.getTitle()), + newActivityContext); default: throw new CommandException(MESSAGE_UNKNOWN_VIEW_TYPE); } @@ -78,8 +80,19 @@ public CommandResult execute(Model model) throws CommandException { @Override public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof ViewCommand // instanceof handles nulls - && type.equals(((ViewCommand) other).type)); // state check + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof ViewCommand)) { + return false; + } + + // state check + ViewCommand v = (ViewCommand) other; + return type.equals(v.type) + && targetIndex.equals(v.targetIndex); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index 13f6dd2cdb1..33dec544445 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -21,8 +21,7 @@ import seedu.address.model.person.Person; /** - * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for - * {@code DeleteCommand}. + * Contains integration tests (interaction with the Model) and unit tests for {@code DeleteCommand}. */ public class DeleteCommandTest { diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 2d37f9e5fa6..35e39cdd58c 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -30,7 +30,7 @@ import seedu.address.testutil.PersonBuilder; /** - * Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for EditCommand. + * Contains integration tests (interaction with the Model) and unit tests for EditCommand. */ public class EditCommandTest { diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index e7503f58a22..9987fbb21cb 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -1,5 +1,7 @@ package seedu.address.logic.commands; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.Assert.assertThrows; @@ -69,4 +71,22 @@ public void execute_activityListIsFiltered_showsEverything() { assertCommandSuccess(new ListCommand(CommandSubType.ACTIVITY), model, expectedResult, expectedModel); } + + @Test + public void equals() { + ListCommand listPersons = new ListCommand(CommandSubType.CONTACT); + ListCommand listActivities = new ListCommand(CommandSubType.ACTIVITY); + + // identity -> returns true + assertTrue(listPersons.equals(listPersons)); + + // same values -> returns true + assertTrue(listActivities.equals(new ListCommand(CommandSubType.ACTIVITY))); + + // different CommandSubType -> returns false + assertFalse(listPersons.equals(listActivities)); + + // null -> returns false + assertFalse(listActivities.equals(null)); + } } diff --git a/src/test/java/seedu/address/logic/commands/ViewCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java new file mode 100644 index 00000000000..95a869101b9 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java @@ -0,0 +1,130 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +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.Assert.assertThrows; +import static seedu.address.testutil.TypicalActivities.getTypicalActivityBook; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIFTH; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.CommandSubType; +import seedu.address.model.Context; +import seedu.address.model.InternalState; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.activity.Activity; +import seedu.address.model.person.Person; + +/** + * Contains integration tests (interaction with the Model) and unit tests for ViewCommand. + */ +public class ViewCommandTest { + + private Model model; + private Model expectedModel; + private String expectedMessage; + private CommandResult expectedResult; + + @BeforeEach + public void setUp() { + model = new ModelManager( + getTypicalAddressBook(), new UserPrefs(), new InternalState(), getTypicalActivityBook()); + model.setContext(Context.newListContactContext()); + expectedModel = new ModelManager( + model.getAddressBook(), new UserPrefs(), new InternalState(), getTypicalActivityBook()); + expectedModel.setContext(Context.newListContactContext()); + } + + @Test + public void constructor_calledWithNullArgument_throwsCommandException() { + assertThrows(NullPointerException.class, () -> new ViewCommand(null, INDEX_FIRST)); + assertThrows(NullPointerException.class, () -> new ViewCommand(CommandSubType.ACTIVITY, null)); + } + + @Test + public void execute_validIndexUnfilteredList_success() { + model.setContext(Context.newListActivityContext()); + Activity activityToView = model.getFilteredActivityList().get(INDEX_SECOND.getZeroBased()); + + Context newActivityContext = new Context(activityToView); + expectedModel.setContext(newActivityContext); + expectedMessage = String.format(ViewCommand.MESSAGE_SUCCESS, "activity", activityToView.getTitle()); + expectedResult = new CommandResult(expectedMessage, newActivityContext); + + assertCommandSuccess(new ViewCommand(CommandSubType.ACTIVITY, INDEX_SECOND), + model, expectedResult, expectedModel); + } + + @Test + public void execute_validIndexFilteredList_success() { + // Filter the list to only show the second person (Bob) + Person personToView = model.getFilteredPersonList().get(INDEX_SECOND.getZeroBased()); + showPersonAtIndex(model, INDEX_SECOND); + + Context newContactContext = new Context(personToView); + expectedModel.setContext(newContactContext); + expectedMessage = String.format(ViewCommand.MESSAGE_SUCCESS, "contact", personToView.getName()); + expectedResult = new CommandResult(expectedMessage, newContactContext); + + assertCommandSuccess(new ViewCommand(CommandSubType.CONTACT, INDEX_FIRST), + model, expectedResult, expectedModel); + } + + @Test + public void execute_invalidIndexUnfilteredList_throwsCommandException() { + model.setContext(Context.newListActivityContext()); + expectedModel.setContext(Context.newListActivityContext()); + + Index invalidIndex = Index.fromOneBased(model.getFilteredActivityList().size() + 1); + ViewCommand invalidCommand = new ViewCommand(CommandSubType.ACTIVITY, invalidIndex); + + assertCommandFailure(invalidCommand, model, Messages.MESSAGE_INVALID_ACTIVITY_DISPLAY_INDEX); + // Current Context should not change if command failed + assertEquals(model.getContext(), expectedModel.getContext()); + } + + @Test + public void execute_invalidIndexFilteredList_throwsCommandException() { + // Filter the list to only show the fifth person (Elle) + showPersonAtIndex(model, INDEX_FIFTH); + + ViewCommand invalidCommand = new ViewCommand(CommandSubType.CONTACT, INDEX_SECOND); + + assertCommandFailure(invalidCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAY_INDEX); + // Current Context should not change if command failed + assertEquals(model.getContext(), expectedModel.getContext()); + } + + @Test + public void equals() { + ViewCommand viewFirstActivity = new ViewCommand(CommandSubType.ACTIVITY, INDEX_FIRST); + ViewCommand viewFifthPerson = new ViewCommand(CommandSubType.CONTACT, INDEX_FIFTH); + + // identity -> returns true + assertTrue(viewFirstActivity.equals(viewFirstActivity)); + + // same values -> returns true + assertTrue(viewFifthPerson.equals(new ViewCommand(CommandSubType.CONTACT, INDEX_FIFTH))); + + // different CommandSubType -> returns false + assertFalse(viewFirstActivity.equals(viewFifthPerson)); + + // null -> returns false + assertFalse(viewFifthPerson.equals(null)); + + // same CommandSubType but different index -> returns false + assertFalse(viewFirstActivity.equals(new ViewCommand(CommandSubType.ACTIVITY, INDEX_SECOND))); + } +} diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java index 134e60a4c20..1e2f4732a59 100644 --- a/src/test/java/seedu/address/testutil/TypicalIndexes.java +++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java @@ -9,4 +9,6 @@ public class TypicalIndexes { public static final Index INDEX_FIRST = Index.fromOneBased(1); public static final Index INDEX_SECOND = Index.fromOneBased(2); public static final Index INDEX_THIRD = Index.fromOneBased(3); + public static final Index INDEX_FIFTH = Index.fromOneBased(5); + public static final Index INDEX_EIGHTH = Index.fromOneBased(8); } From ee1c3153f843b4ee1541dd1fedc0ae547e3893ff Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Tue, 29 Oct 2019 04:31:36 +0800 Subject: [PATCH 06/13] Add PersonDetailsPanel to display full details of a contact; add icons --- .../java/seedu/address/ui/ActivityCard.java | 6 +- .../java/seedu/address/ui/MainWindow.java | 5 ++ .../java/seedu/address/ui/PersonCard.java | 4 +- .../seedu/address/ui/PersonDetailsPanel.java | 48 +++++++++++++++ src/main/resources/images/address-icon.png | Bin 0 -> 1700 bytes src/main/resources/images/email-icon.png | Bin 0 -> 1709 bytes .../images/participant-count-icon.png | Bin 0 -> 2452 bytes .../resources/images/participants-icon.png | Bin 0 -> 1373 bytes ...placeholder.png => person-placeholder.png} | Bin src/main/resources/images/phone-icon.png | Bin 0 -> 1853 bytes src/main/resources/images/spending-icon.png | Bin 0 -> 3083 bytes src/main/resources/view/LightTheme.css | 55 +++++++++++++++++- src/main/resources/view/PersonCard.fxml | 4 +- .../resources/view/PersonDetailsPanel.fxml | 55 ++++++++++++++++++ .../logic/commands/ViewCommandTest.java | 1 + 15 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/address/ui/PersonDetailsPanel.java create mode 100644 src/main/resources/images/address-icon.png create mode 100644 src/main/resources/images/email-icon.png create mode 100644 src/main/resources/images/participant-count-icon.png create mode 100644 src/main/resources/images/participants-icon.png rename src/main/resources/images/{profile-placeholder.png => person-placeholder.png} (100%) create mode 100644 src/main/resources/images/phone-icon.png create mode 100644 src/main/resources/images/spending-icon.png create mode 100644 src/main/resources/view/PersonDetailsPanel.fxml diff --git a/src/main/java/seedu/address/ui/ActivityCard.java b/src/main/java/seedu/address/ui/ActivityCard.java index 21543b767bf..c9e4b8d83ed 100644 --- a/src/main/java/seedu/address/ui/ActivityCard.java +++ b/src/main/java/seedu/address/ui/ActivityCard.java @@ -39,9 +39,9 @@ public ActivityCard(Activity activity, int displayedIndex) { this.activity = activity; id.setText("ID: " + activity.getPrimaryKey()); index.setText("#" + displayedIndex); - title.setText(activity.getTitle().title); - int numParticipants = activity.getParticipantIds().size() + 1; - participantCount.setText(numParticipants + (numParticipants > 1 ? " participants" : " participant")); + title.setText(activity.getTitle().toString()); + int numParticipants = activity.getParticipantIds().size(); + participantCount.setText(numParticipants + (numParticipants != 1 ? " participants" : " participant")); } @Override diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 406ab97fd29..52a741d267a 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -33,6 +33,7 @@ public class MainWindow extends UiPart { // Independent Ui parts residing in this Ui container private PersonListPanel personListPanel; private ActivityListPanel activityListPanel; + private PersonDetailsPanel personDetailsPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; @@ -156,6 +157,10 @@ private void contextSwitch(Context newContext) { case LIST_CONTACT: contentContainer.getChildren().add(personListPanel.getRoot()); break; + case VIEW_CONTACT: + personDetailsPanel = new PersonDetailsPanel(newContext.getContact().get()); + contentContainer.getChildren().add(personDetailsPanel.getRoot()); + break; default: // Do nothing (leave content container empty) } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 19d0608f8f1..2cef86d4549 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -44,8 +44,8 @@ public PersonCard(Person person, int displayedIndex) { this.person = person; id.setText("ID: " + person.getPrimaryKey()); index.setText("#" + displayedIndex); - name.setText(person.getName().fullName); - phone.setText(person.getPhone().value); + name.setText(person.getName().toString()); + phone.setText(person.getPhone().toString()); person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); diff --git a/src/main/java/seedu/address/ui/PersonDetailsPanel.java b/src/main/java/seedu/address/ui/PersonDetailsPanel.java new file mode 100644 index 00000000000..9f8fd4ad919 --- /dev/null +++ b/src/main/java/seedu/address/ui/PersonDetailsPanel.java @@ -0,0 +1,48 @@ +package seedu.address.ui; + +import java.util.Comparator; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.Region; +import seedu.address.model.person.Person; + +/** + * Panel displaying details of a contact. + */ +public class PersonDetailsPanel extends UiPart { + private static final String FXML = "PersonDetailsPanel.fxml"; + + public final Person person; + + @FXML + private ScrollPane detailsPane; + @FXML + private Label id; + @FXML + private Label name; + @FXML + private Label phone; + @FXML + private Label email; + @FXML + private Label address; + @FXML + private FlowPane tags; + + public PersonDetailsPanel(Person viewedPerson) { + super(FXML); + + this.person = viewedPerson; + id.setText("ID: " + person.getPrimaryKey()); + name.setText(person.getName().toString()); + phone.setText(person.getPhone().toString()); + email.setText(person.getEmail().toString()); + address.setText(person.getAddress().toString()); + person.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + } +} diff --git a/src/main/resources/images/address-icon.png b/src/main/resources/images/address-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0936d4000e4e5ba86da424d2d8cf0b9d78628df7 GIT binary patch literal 1700 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(3Y0q<;1l8s6bFK|w6st#@b&ctvZJG;fxLi#fT*Y_AR{g=E;2GQCMG5#A_B+; z$^yk9AUr%ACaiUZXHxo`$V8Bhcw4kUq6KrTcC$OZz4 zAjAX+8zKl-16B?)0j?M*0@4Yy4z3F#0w<9fKsFq})dLxDHe42BIK)z*Af^JiN;Fyg zDsd?WS_Ib!_ZPAiaKY>L%}KymoK_O#7tFxO%ErmX#m6roC?qT{DJ3lMpm*woR{)!ozAKVjnJ=`&`{ zo-=R$f`yBgEMK{P|V^&0Dwc-hc4$@snpS zUcP$$=I#6UA3lEi^!dxzuiw7^`0?}C?>~S4{aYh_g$d|F&H|6fVg?4j!ywFfJby(B z0|WChPZ!6K4ClAgU&dc{5NKOn(ZJsHh*iscYSp4e9Sx5fJ05j%%=^l~svqDIATVJX z+awc@)cYHz0GUh$#U%9X3zNgXq^}cEMuRMMP1U7N{y4N`3RUR#VI;+6sOvDd~ zPSXcZn3%5wtH>@_Jo4Lk+122KiL=tr{_8nw9&|D=Dz*ODGrgdTmsJ)v<*xG&E_T`J z^;Au3!&Rv}bC$TdY`DC}I5Ar=c_9Um`}vDsw}W+J=A7*!rb#4ThY9p>kF>^JZhqBade(| z(u&44ycK_xy!co2{&k$>vZG#kO7)ZASz8+=_d6_*zOv2HGKy(NlEnuHAIrz~QDPlG zQj5Pkh}H>R7CT*_D6>oT+sdDxD;Bz@{Ly;5psZi*_4ykw@+@xXy{lazslTnh zMoqh|Zr#!Yu{jeMCHKFQ42awKeR)FXeja)8?-~CTw|R8;+&?P3phogn@G03ym8CX^ z)iNi1+#SRHD&kGr1g09vb+Kxxd!8uIo0RcKFSL1$_xI1P-r z7~`hGqu(Y=0o4kepJcazb+)Ra)PCc3hi!k@qwm9~3)5`SeC)4n|Ybd@Vlf7`?5HHzDtf973GvpI0yLh1}ZJCDoiCl-kl zru|QSu-yJb!~H5%?&cZ6Z$pC~Nu?YyJ<*XpLD0(dty#j;Ia4ki?NpIcc_hUV)BI!y x8`E_KMF)*ZENKkI}{E=MnMLW3{0A#M9N!Wt~$(695NC;UEA2 literal 0 HcmV?d00001 diff --git a/src/main/resources/images/email-icon.png b/src/main/resources/images/email-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..13b1d238fa643ccbe1413dc7884a94e6eae77081 GIT binary patch literal 1709 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(%D})R8Q>G*3KR!|hK7c;w6xIBP)|=!AQ>AQ3nZhXqobmtAl%5vNFXC7CMF^x z0wM)r#Kpw{)d1N*EkH(icsNiEoB`wlH3DTJB*Z|t2#^6(2_b=M;B1Hj2p3HpA_!Cf z0YEN90Wt}cg6jgZk&T7xLN*+32t*@R?PwZ-T!;y9aR>vA#B>Il0$g06Mu-$L18yU- zAW#{c3uMF9;9>(6!_^>bL}o**zPh(b7MLGKz_UcG+v=Iy)p?>~I}^y%}L zuV24?|MBDJuiwA_{QdVlb9Xk-^_&GBk;M!Qe1}1p@p%4<6b1(7cuyC{kPPRyGoD9Z z4iIVY-@z_j_}Haz(GGU4CT`b|IS*V8?A^X&!oo!zkB%@-S+<1P^|$z~;-ZYnx3+u_ zv-^1GyYuAYNx!Qzi;8En2WW_JwK^#}Uu-yh@UO^Eb_vyvlMBQ`KH79QC-0Au5%RsT zeM0r6Gv8Q0zh#m8^CI?;ujjLG4>Qc`Zg54_{CIix={gb1DG&0N_s(7LLQC?F_fFk| zP4_J>1&8-YS2M<_G^_XjKBV(*X<@$`+vGJZx1RT|-ZF=uW76xRf%9%9E>q!NR(7`h zPVss(zK)GP#|`)W=A5Qt{H*LN|DCJXFEJ{9>iMI+Ltmlcl;555+yzbzqEhqT@Ahf! zVDOvdcsnIz>#^%!+Ig72YMV?){ zf`QL+*JIWg1#`auJFIQusPo;8r9^6vCCE$~neEcdWCf?%~KM*w4YwS z-Squfz&ocyrL*=Qv-aBI=w|Sf_v!1_WADGr6?Ciq;Ty&Iwf5@{PIC_qwXG6AjS~cG z+0Qp$ydhWGKd&Iyx+nXmQdD32*gfb97AGY$~51 zb~lr`me-sy=n!vGQ;*s&XWyR;#-5!ow0E{Hv0EN@K|#f%e*(Y3Uo&6-`@d!KB$n(w zkas~r$s@aGihRP=yJc^~IK>?=#b1grLMcJ*vdq?d+zR*d=r*daUWzmKPV}$~fJncjK?gxtbU$&4q6na^JAbe{_yt z=iOQnNAI<3AJ~8T_`K7ICx^vj&(9ysrv(|`u-c#g`JbsUz%83o@ToKpkC(t?M-7Pr hi-?8btiZrf&-h2S$iR8>k2#=<#naW#Wt~$(696wA+(G~V literal 0 HcmV?d00001 diff --git a/src/main/resources/images/participant-count-icon.png b/src/main/resources/images/participant-count-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1ca5de50c60d2351a7a059cd4a1a0ff976bb62 GIT binary patch literal 2452 zcmZXU2{e@Z8^^~om9d91(PS)bF0yA5S*O9c8e7H^W3r_Pk@d=w5y?z0Q?{-pOcJK- zOhlBeZA7v}DQhClxHR|w>p$nrxySvT^FHtQ`F=mo^Pcyd_q?fgwrEk<9vB1y5yhM| z$AP=&uWN?@s7%Y0Ujbhz4s8ml8jzm_ji9dy)&v5nxgosi1%*KPL+xxFEP(Im=olX# z@8jcx!C*iIErCFAb#(>8)6)}=#{&V5ySuxKiwh7q9L~+n?eyu>Kyxv!27t4(Gl;+l z5C8@h06=gnXh8&EP=UkM+z6Neb7xMc}wxA^}a*^+J{d8>FM zJi(24JWl|B3&SOOCLn?4@jL;re{1ekS#~T1e0DFwaJKdk0YT_?n24yDxP;_RnO(bO z;qX0j@(2YaQb}25|G`6tRn^orj%aG@>ggXfKp7gHFfp^VM4!Z1S=(T3f44h@b98cc z!MnSAczO}Mz5V?B&jp^p5PUHtH0*L@R7`AK{FTI{6jEwhdd7{+OfuzW)}Prq)Z4lF z1$X``Dk&{1D=(*2Rz0YuKdf(PY-(*|w0At|?0VYM*FP}$^406tZerAhQe{X3EiL0*5mXfEWCB<8gnwvisC@z=Z^R-h-@$w02 zK^f>bK^by+&tC)yNt1RzWmAdd%w^53r30*W${g+8T*Xq= z?E(@^=CFgr=c%AbYVB;bm(KW&Q?oANhQ8KKasx?4oxd5DcUVWs-8rN-y-Eriy;WO@ zYfW9ISbnjxQc6%2`C|24QqYY4mIY7ZAGKu;jpj+ zSYm|}3mF#x*ExW-sc_m?#%>j6dOGyaWUobJdT16uyKtM&AZr-6x6RWvdb)QyncCFS zc+VX*Q*fnJT?Jj?stH4SRXj)6<7{7^)f01WY7)7Ay9b%2Tsmjigtk%_nHtq=F(s)n zF>)dspoh0}XAOHq68+G$-{7Ex+)Nb8D#C6cc1bEjDp zGR8J664>NYd`#>%#B7R#1f#7qw3pap+BcGO!9&XtgReNO?y;g`7A54^)SEi`VBDWv z(#<%e>Nt}ud%q|&R)^8(ljTh76P*z{yV~=!Xm`7uX$uqSy*58jPez2PiaYI9bWT01 zAeqyeN48#Sw&x`DY^vwevg@m4dpTnFiH4jaN-JCN0RO;B)OO@_+FJ$f;{#e>D!tEz zhby#oXtlLUWkik8*n}y~bkb()@|y|_z47yN#cwj}vkMKi!Z2u8#H$E4b(6pHsh6Jy zVxo?9EW`c0|NfgBq^Y!0Jbtl6_(%ghe6ql2`@F&Bj7t7`(PW>zxlQ$_vgN`J9>V^Y z%$8*vH{rZhdsxFbgPqDpiae7l|4VSdaKcn zlYahonb|gbrr0pcqI{A3gKxxqs9LqhD2empDeB2<`#>A^I=t6_@Q*E!JojcqmI{wNmR zxJ9D*J^Of2VMZk*L2c(}%l^y8hg#klpE&sNcpWDXdMSSFW9EH|V(l}xu58&oJtL)| zPh^frFC%Y-{;qm!A8oWz&O8*`KGwOU;gLTWA`ppwmWN$Bq}5sLHg7@67;5%f(azl+ z*Gw^xipEA38b^ob$HTu@#rG%fQ;NMWO~&q%n`#uCfF84~yvUk{1R`4K>(M2oz`nHMor7*m z=&{w#eq%!Zt0R$~T`zBgCeG^ZxZ=o@I^Z~Q@?!TbvgC>1(mO#w~`R?-)-FIW*~ zH>)1y3lGnsT(sSN6Dg^>uJ=fvz`qcfLLp<>YZ{LgJ(&HHQh6p(8~Q3rxrIHMq~qTO z?(HY=*EqR1XuV0_98o67o*A-PUz0X!pSbvmQVuumw%soOJmq8oB0` zrFY)67VTfY6X?;dz}M1s^=}eZ?}~A*pv|P!-Q18@LblhShJ24EYHh0X2{bc&fzZ`p zeaDoChEjcj#nidXY~KXdL1mAcPt^E(>0%X08^ae6S=-|5QH7!3#bMK!bSr*_(fhZr z=c>e3ReDOjvIE*8*YtcX$EP;EiyZp=7f1e_EWG+pvhoBT{ASqY4CA!&gi< literal 0 HcmV?d00001 diff --git a/src/main/resources/images/participants-icon.png b/src/main/resources/images/participants-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fae537b3d4e136e2789be7fe42e04f66df25b3ea GIT binary patch literal 1373 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(3Y2RI@Ck7Riid`VrlqCj=H~kP`T`jN0RagK2~kl|v9Ym0ModghL_`Eo4G_e| z#X-b@BoKs$hXZ9JBO`%~XfOb>fr^0u$O9^XaDgO*4Htnh;IcsVKoPJ$5CbR&1!to%Fr^^2!0kda3a%YlBb*J_1!tgXhl@)^@+}3% zL48S(UoZnRD?1mLfPkQwgrt`*ckkbS`1tA5=PzHsegE;}=da(t|NQ;;&&qj=8_+471s;*b3=DjS zL74G){)!X^2BzDdE{-7?&Tp^1j1~%%VEquCnda8*6(*G%6p_ijHf@&f7KLqDskf3^ z6M1+T`IZ>|uQEQIIOFMF<2%dq%j)N+y{n$Lb8#HMf#)O@&q@E1?|!_wbLYzn^E~Iy zXX?^kk=MV<_r8wcP@Ewj^CNGGZtL{s2p)x5_oI#OFI#${Jyq|b&FPQ{TSJT@o(Y|e zKcUEV%9Y2$<#UdxJ7g`|X?MZ&Gqru$NCea82b?&BV?9c6n2acINDh`fX5~7GFH| z{;ZOD*+XzhPamlm2G%|5$w&U<#_Q!5PX zrT9y3n{Iw-rIEXN&$T(nmR_%_vX^^hFj4j1vdnqcXGzBVzFHGM(XLQ_{cG(#*J2Kt zIz}F8R(xvtOi!Bq#kHOv_4&C`T>aa4EPfsFuXfu0%;iG#%T<-XqJ&h}T)Ni7adFoC zLg&@0YuwF!6DK@8i=0lP~^ci~9SLBWd0>nVs?6Rx)#Q1Mcm)o$7kx+M8V)TV)n5 z=IvVFH|w)(=TWV@v;Lm{Ysw*;6L3?;eEIQUQC4lfwby#;4>yJXV7s;H=f!=$6L0=} z=XdtnoBvJG{MXs?HS_tT7N6$&_|0s!slUSehj$wC6`$x-MF(GDzW=;o`fgKKS+2_Z z$*WCW=WgDw`)OxXaL9%F9cwq+tNG>$c;yLXN#`^q@qE#j_5h{CExrcd#KY%quML@3 SyAGK489ZJ6T-G@yGywp{7FLu1 literal 0 HcmV?d00001 diff --git a/src/main/resources/images/profile-placeholder.png b/src/main/resources/images/person-placeholder.png similarity index 100% rename from src/main/resources/images/profile-placeholder.png rename to src/main/resources/images/person-placeholder.png diff --git a/src/main/resources/images/phone-icon.png b/src/main/resources/images/phone-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0de651e1747ee865046c5fad38642b9a820ad4c8 GIT binary patch literal 1853 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(%D}*672p%%3KVZ>Xb24rO-M)plD@vaNl8i3(a~{nagmXcK#|zkSO_B~CMF^x z0w@BM0xAHqfsClAC?Er<2FM5x4+pA&Gl05)B0!aB42TxEVxV@Q8n_@tJx~xL0@Mp+ z00G1hAOk3cEDK~q)W8M7%0cQOA`k{L8)6!o2%HNs4M;)&TrrRfR0AiW(l9}YI9976 zCcxDL8JK3m1(B8EVk0{h;v}F-tb({q0E#2K3eLu52;3HkMG#{{Ux{1+rk=eeL4Lsu zOl%yST)ce3BBEmA5|UEV(lWAg@(PMd$||aA>Kd9_+B&*=`UZwZM#d(lX66cw$;l~cY3Ui6S=l*x`9;MgrDc^>)irhXjje5+ zUA=u1CQY6;bJm-OzCckkVQ z@bKZI$4{O-efIpt%hzw-zI*@v!^cmbK7aZ8_1pI!KYsrD{rk_~fB!hUZv6&>NdS zvY3H^?=T269?xHq!oa|M*we)^B*XdbjOXFPjv_~s!$r8oayEX~E87_Urc1Q?z0!>h z-{S&8LPT7aN;)l4xpCp={W(wW=4_gLcfy$-c^mcp#X)8FYroG+NiR>kK2halz1OWf zdoRy=_cC{DhXXtZRn@r}cpSM9~w~4Udk9|VB zzf64nB>!Pc{_4!_W}oh+IvtYI%20Z*oSbwhN-I-w{%?0xla$~<=4$N|K|T@wsi{W$ z4hQ;t$X97pIvZEhm>ANOFYI~6B8YQ0L(-wNOB#V}#!fyroRnC9T|LCj!TEK%hnjy{ zL5G`y${!hDtIV>i2TwY9>~OQnyyn8n!FhGbbIW{HH3UF9QctX;TCvJ zT*x)%gYe4BAO5rNWN>DD&v|8P1yLswi9*{7HmT#1l!4Vuxl$x8RdJ+~(-_qF^Cb8l2HafzMV zy+Nen8fR&$)z!m64)IRgjy{oJu!5WAR7~sQ6Q4~uLNdE|w`jzbv^q_lX=l-u;cby) z{&mkAwpK0kL-=weekLuil17#W;%O#B4?+E|cU2;hB^zL~IQwk0owR!ww zdC8&D-Kw_9OKSr6KR5pWNb+>+CeE|+3(hi~-xzJuxchj)(j2EK!COfW`D|Dw_-2&L z=Wbjfdvxk1&b4{w3-sC6O^ng3U-H&{bz?S*xR-j&Ci%5&riXV1SS>tIwKsiHnuNHU ziqFDp78~cw9SY%pdZ@t3u=LpJgB3z;1q&xW@cO`bZP)#b9>=Q*dOWHX(*u+5q)Z7& z*3n`wR214Xd8K~ctveaN0>b&8IC*8{_~v$QxL?=A5op-(nu&AX+$)nMir=d56!7>k zXL+AX;l2NC%F(BO7svK3v41}2?yjp3YVAE#XU5*UqWLlI>(5IM)%4cyi{V&$a!2~l z7`7{?{{K(h_B+RYjaYr%@qJsBN-i3H{wgB!N@r(wp-xS8z*VR3vaWWQSCrb$X`N(d zrEd{?>&42XGxr0|zSB7pch;ob?|wnj?PF)A-SC_Ar2g>3AKVS@Q`fj1IP?^l#~D0b L{an^LB{Ts5f!7nG literal 0 HcmV?d00001 diff --git a/src/main/resources/images/spending-icon.png b/src/main/resources/images/spending-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5050588df818bde94cebe3948ac99f53395a1bbf GIT binary patch literal 3083 zcmV+m4D|DfP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D3!q6vK~#8N?VWpw z9akO4^M@!^Cg(&<2YRj~=}TY^Tk~D0?4x8+fB(mr^0ZU?0JN4O|}szXAWkkjr49 zzrTN?r>AGKv$J!my}f<>@ZrPLt*xy~EiEmJ&CSh=y64$UM@Pp*S69~nuON0Dj8PM{vsh)OnZb{?;Q5unnV}z#x}pq$5X;Ok&)L{rmSX?A^OJyL0Ex zY)wr~wyLTs7Sz_(W_Rt{m2GNj%Hp^zPI{Ss7r}pU$Qk6R-Sm+%JUsk%lx)W6e?jp% zjbs^H#<3Y~BOpi1DT*8%v4UJ@Nq3(&B5xi-u@fkGO{09zo;_A$R2p@4by*@X+uPea zj=U2LmIFroZ*;}iieGN7>KtbSE~OYUayQ}z`2 zgWB+XOg#8`UNb4)JGnm8mrVv6G=Pj8+l_i|6UP4x#<{K$Xj908MyHHH&YjXI!(dl1 z@Q;;y!QB|`J%(k;Bwpev-Wc+`#yQv2w`AC{V~15n4~i<)?^oLDVX9*onAnUA6 z2OO|WntZpZ>K+l!Bbqt*1y>FwGJa>OIZx>EjAZuf(b?Il#oE25ntOzBk83LE7hK9v zcF|OGo)|38+8m%68qR4n)!d^(4iFU93U5=@SyGxL&5YZ0NVEfz@DgU^|6MW`+Mi0a z13Y-sQ0i*_|1A`EVH!G#OtV3&_D$gc51Q6#5rpDet>zYD801l~5eu;^>eDR57Q*gR zZ7K)&;cZ3e;|fmsA4Z#ppSA$TWH9g?&z|Dv+%^Qpe2DAU1l{xe+bRQ3s4mcI_ch8_ zxSv(jwY9a4$>7CoMdV{sJHUoYZ^rqNSO+vWHwW&wxCF^6nf=e@07aWo*F9R#0hBH2 zMW^yOKR3pSef#!lrlt=v%QgpSHx&nDhlYmgjLL3NfCGlWz2xIx5ysbT3RVh|1-X{N zWsF-TSqsUh_XqEy1$3w}YP&-Se!9?B1ZBT8)wIxjlLc1=eDMcHBh1Bk}9;H;vs)pDg!W@{tZUJ4)9p91`JVt7QTJpN$w}}%fqgO{UD-O zh`0w#x9$+3JVMS7{ZU@^w0KfpMX5R3+aly2;3pXH5%61oxt>w}9j<3o*I%v?u49av z5Cna%4hy}L=&!-3?G`aI26>^*E9KaPF9zbF^dRGD#Vbeo4XkG>QytZfqu(I#zF0-i z>o{E7C4UBbPYr-C4i67+HKwQ>Ay}+i6RtujOb(Z>=IrUK=&q0W|K)m)DA|isZZ~Gx zIHL1E-3ksU1ij~^Kanzt12k>D!1aD(p7IjLf0S9mWRmuP$_Z`1$QeY(YuHBbjviyG z_=yf4#@mao?)g+2N>@b1G=oAqQ|K8yp(vOTTn(`bZmqRyTw)lu(~X&#N}@F6j> zb&wC`Q966tGz+yo9rR97x$DPXBpWhXw`r6Gu*0gU9*r<+sD+naT;`xwuW9$Xy&KBT zBapW}Jrfim+Tf#JqR*c4e46s;v!bvL5R{{}^-G#~5knW;pBMQZ_Ozl7$Vbrjv<*pk2{ZE7J$q^fUi8nLaXFwAc+*g1N!-~}l~Z?VXlSU#uqlpQ zaDWFbezXWe@x+`x6(l$5bOv6nhJAP{>mdp%y&1P2)E73pah56+1vsE=C*xd*uwo!tgY-8m<27bX;s2}-4Kn&WK7M9q zp1$tMI87sU=t?6^Bdi#Msy+Oji!eWe&Yt=~T}`d;Hf9SZ7~i7~Y|JoD(8;(T>BU1H z{sH$d`^&wPaW=tC`%Q87G#}`zm2qv(xM7IO@1&F0MS!5WFAPgL8K;liPw4oe_uNCd zBPDy)y141+pi%Hu6c|OISIQM(rnoHSQO=%5c7TY6`kuNVquQ7k14WA#H~Dk*pqY+8 z!Z6A>^5i0n`?JLwFhqImXHQFVfCy#pLYNoHn{#?e**e)MgorTb&YqU+0FMy(1XxDM zTtt*>^%xaOTS^a-O|vA;Wc&u!GnJ{1>Z(mXk8&V32Z)Gs(3X+s_0C!*v1 zK!3gVIL^4h%knCYS)ub)?iYDBr&*PD9GS+==g-$|Ga@O&Tzy3m7UzO1E=WG~y0J1w z@BWH9pb(L!ZqqsYRCA9oY^c2_t|u)9&>!_)Ar0pC^8MvDPStagP^_fA zC)(c*wt>g}<+Qn^I)d&k?Mqr2lX{*;_JS*8@3$~dojUa8cqHd3#M|N+Vi%<6!;kEdBefdH7s`&nVYN=;y28y{7w=3K6Mc z-MuH!kCTpa)!LzhYb)0}u3y0DcXItOPI;?gmr_b8rIb=iDW#NBN-3q3Qc5YMlx*6v Z<^SXH&wYahew_dS002ovPDHLkV1hPr^jZJ_ literal 0 HcmV?d00001 diff --git a/src/main/resources/view/LightTheme.css b/src/main/resources/view/LightTheme.css index b5b699a7383..8d043725c40 100644 --- a/src/main/resources/view/LightTheme.css +++ b/src/main/resources/view/LightTheme.css @@ -52,6 +52,7 @@ .content-display, .card-list { /* Suppress blue focus ring for result display */ + -fx-background-color: transparent; -fx-focus-color: transparent; -fx-background-insets: 1, 1, 1, 1; -fx-border-color: #c0c0c0; @@ -66,6 +67,10 @@ -fx-highlight-fill: lightblue; } +/* + * ================ LIST CARD COMPONENTS ================ + */ + .person-card, .activity-card { -fx-padding: 8; -fx-background-color: transparent; @@ -79,7 +84,6 @@ } .person-card .person-phone { - -fx-padding: 2 0 0 0; -fx-font-size: 15px; } @@ -96,7 +100,56 @@ -fx-font-size: 16px; } +/* + * ================ DISPLAY PANEL COMPONENTS ================ + */ + +.details-container { + /* Suppress blue focus ring for result display */ + -fx-background-color: #dbdbdb; + -fx-focus-color: transparent; +} + +.person-details { + /* Add horizontal divider to visually separate details of contact from activity listings */ + -fx-border-color: linear-gradient(from 0% 0% to 100% 0%, #dbdbdb, #ababab, #dbdbdb); + -fx-border-width: 0 0 2px 0; +} + +.person-details .image-container, .person-details .data-container { + /* Add internal padding */ + -fx-padding: 8; +} + +.person-details .person-name { + -fx-font-family: "Noto Sans CJK SC Black", "Segoe UI", sans-serif; + -fx-font-weight: bolder; + -fx-font-size: 23px; + -fx-text-alignment: center; +} + +.person-details .tag-list { + -fx-padding: 0 0 4 0; +} + +.person-details .person-phone-container { + -fx-padding: 0 0 2 0; +} + +.person-details .person-phone { + -fx-padding: 0; + -fx-font-size: 18px; + -fx-text-alignment: center; +} + +.person-details .person-address, .person-details .person-email { + -fx-padding: 0; + -fx-font-size: 15px; + -fx-text-alignment: center; +} + .tag-list { + -fx-padding: 0 0 2 0; -fx-hgap: 5; -fx-vgap: 3; } diff --git a/src/main/resources/view/PersonCard.fxml b/src/main/resources/view/PersonCard.fxml index 030221ecacd..e78c272e2ab 100644 --- a/src/main/resources/view/PersonCard.fxml +++ b/src/main/resources/view/PersonCard.fxml @@ -19,9 +19,9 @@ - - + diff --git a/src/main/resources/view/PersonDetailsPanel.fxml b/src/main/resources/view/PersonDetailsPanel.fxml new file mode 100644 index 00000000000..21880ef5c08 --- /dev/null +++ b/src/main/resources/view/PersonDetailsPanel.fxml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/seedu/address/logic/commands/ViewCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java index 95a869101b9..7af9d4e9af4 100644 --- a/src/test/java/seedu/address/logic/commands/ViewCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java @@ -73,6 +73,7 @@ public void execute_validIndexFilteredList_success() { Person personToView = model.getFilteredPersonList().get(INDEX_SECOND.getZeroBased()); showPersonAtIndex(model, INDEX_SECOND); + showPersonAtIndex(expectedModel, INDEX_SECOND); Context newContactContext = new Context(personToView); expectedModel.setContext(newContactContext); expectedMessage = String.format(ViewCommand.MESSAGE_SUCCESS, "contact", personToView.getName()); From 5d4d1016d2ad5c3fc3f02964c309f5a41fe2910f Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Tue, 29 Oct 2019 04:32:42 +0800 Subject: [PATCH 07/13] Add ActivityDetailsPanel to display full details of an activity --- .../address/ui/ActivityDetailsPanel.java | 46 +++++++++++++++++ .../java/seedu/address/ui/MainWindow.java | 5 ++ .../resources/view/ActivityDetailsPanel.fxml | 49 +++++++++++++++++++ src/main/resources/view/LightTheme.css | 20 ++++---- 4 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 src/main/java/seedu/address/ui/ActivityDetailsPanel.java create mode 100644 src/main/resources/view/ActivityDetailsPanel.fxml diff --git a/src/main/java/seedu/address/ui/ActivityDetailsPanel.java b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java new file mode 100644 index 00000000000..debf41459f5 --- /dev/null +++ b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java @@ -0,0 +1,46 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.Region; +import seedu.address.model.activity.Activity; + +/** + * Panel displaying details of a contact. + */ +public class ActivityDetailsPanel extends UiPart { + private static final String FXML = "ActivityDetailsPanel.fxml"; + + public final Activity activity; + + @FXML + private ScrollPane detailsPane; + @FXML + private Label id; + @FXML + private Label title; + @FXML + private FlowPane participants; + @FXML + private Label participantCount; + @FXML + private Label spending; + + public ActivityDetailsPanel(Activity viewedActivity) { + super(FXML); + + this.activity = viewedActivity; + id.setText("ID: " + activity.getPrimaryKey()); + title.setText(activity.getTitle().toString()); + + int numParticipants = activity.getParticipantIds().size(); + participantCount.setText(numParticipants + (numParticipants != 1 ? " participants" : " participant")); + + double totalSpending = activity.getExpenses().stream() + .map((expense) -> expense.getAmount().value) + .reduce(0.00, (acc, amt) -> acc + amt); + spending.setText(String.format("$%.2f", totalSpending)); + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 52a741d267a..21b5fb061cd 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -34,6 +34,7 @@ public class MainWindow extends UiPart { private PersonListPanel personListPanel; private ActivityListPanel activityListPanel; private PersonDetailsPanel personDetailsPanel; + private ActivityDetailsPanel activityDetailsPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; @@ -161,6 +162,10 @@ private void contextSwitch(Context newContext) { personDetailsPanel = new PersonDetailsPanel(newContext.getContact().get()); contentContainer.getChildren().add(personDetailsPanel.getRoot()); break; + case VIEW_ACTIVITY: + activityDetailsPanel = new ActivityDetailsPanel(newContext.getActivity().get()); + contentContainer.getChildren().add(activityDetailsPanel.getRoot()); + break; default: // Do nothing (leave content container empty) } diff --git a/src/main/resources/view/ActivityDetailsPanel.fxml b/src/main/resources/view/ActivityDetailsPanel.fxml new file mode 100644 index 00000000000..16d40c2ae27 --- /dev/null +++ b/src/main/resources/view/ActivityDetailsPanel.fxml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/LightTheme.css b/src/main/resources/view/LightTheme.css index 8d043725c40..a99eb07e4d2 100644 --- a/src/main/resources/view/LightTheme.css +++ b/src/main/resources/view/LightTheme.css @@ -110,39 +110,41 @@ -fx-focus-color: transparent; } -.person-details { +.person-details, .activity-details { /* Add horizontal divider to visually separate details of contact from activity listings */ -fx-border-color: linear-gradient(from 0% 0% to 100% 0%, #dbdbdb, #ababab, #dbdbdb); -fx-border-width: 0 0 2px 0; } -.person-details .image-container, .person-details .data-container { +.person-details .image-container, .person-details .data-container, +.activity-details .image-container, .activity-details .data-container { /* Add internal padding */ -fx-padding: 8; } -.person-details .person-name { +.person-details .person-name, .activity-details .activity-title { -fx-font-family: "Noto Sans CJK SC Black", "Segoe UI", sans-serif; -fx-font-weight: bolder; - -fx-font-size: 23px; + -fx-font-size: 22px; -fx-text-alignment: center; } -.person-details .tag-list { +.person-details .tag-list, .activity-details .participant-list { -fx-padding: 0 0 4 0; } -.person-details .person-phone-container { - -fx-padding: 0 0 2 0; +.person-details .person-phone-container, .activity-details .activity-participant-count { + -fx-padding: 0 0 12 0; } -.person-details .person-phone { +.person-details .person-phone, .activity-details .activity-spending { -fx-padding: 0; -fx-font-size: 18px; -fx-text-alignment: center; } -.person-details .person-address, .person-details .person-email { +.person-details .person-address, .person-details .person-email, +.activity-details .activity-participant-count { -fx-padding: 0; -fx-font-size: 15px; -fx-text-alignment: center; From 880337a8e12f849b280d6b8d5c4086842647aa60 Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Tue, 29 Oct 2019 05:17:02 +0800 Subject: [PATCH 08/13] Add methods for UI to lookup associations between Persons and Activities --- src/main/java/seedu/address/logic/Logic.java | 12 ++++++++++ .../seedu/address/logic/LogicManager.java | 11 +++++++++ src/main/java/seedu/address/model/Model.java | 13 ++++++++++- .../seedu/address/model/ModelManager.java | 23 ++++++++++++++++++- .../address/ui/ActivityDetailsPanel.java | 5 +++- .../java/seedu/address/ui/MainWindow.java | 11 +++++++-- .../seedu/address/ui/PersonDetailsPanel.java | 4 +++- .../java/seedu/address/stub/ModelStub.java | 11 +++++++++ 8 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 444f037f266..47a2b9a0b15 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -1,6 +1,7 @@ package seedu.address.logic; import java.nio.file.Path; +import java.util.Set; import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; @@ -37,6 +38,17 @@ public interface Logic { /** Returns an unmodifiable view of the filtered list of activities */ ObservableList getFilteredActivityList(); + /** + * Returns a Set of {@code Person} containing all participants of a specified {@code Activity}. + */ + Set getAssociatedPersons(Activity activity); + + /** + * Returns a Set of {@code Activity} containing all activities a specified {@code Person} + * has participated in. + */ + Set getAssociatedActivities(Person person); + /** * Returns the user prefs' address book file path. */ diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 725d3e26785..0abc19c8e3a 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Set; import java.util.logging.Logger; import javafx.collections.ObservableList; @@ -73,6 +74,16 @@ public ObservableList getFilteredActivityList() { return model.getFilteredActivityList(); } + @Override + public Set getAssociatedPersons(Activity activity) { + return model.getAssociatedPersons(activity); + } + + @Override + public Set getAssociatedActivities(Person person) { + return model.getAssociatedActivities(person); + } + @Override public Path getAddressBookFilePath() { return model.getAddressBookFilePath(); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index f6cc15c246c..97d7f29080c 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -2,7 +2,7 @@ import java.nio.file.Path; import java.util.ArrayList; -import java.util.Optional; +import java.util.Set; import java.util.function.Predicate; import javafx.collections.ObservableList; @@ -175,4 +175,15 @@ public interface Model { */ void updateFilteredActivityList(Predicate predicate); + /** + * Returns a Set of {@code Person} containing all participants of a specified {@code Activity}, + * for GUI purposes. + */ + Set getAssociatedPersons(Activity activity); + + /** + * Returns a Set of {@code Activity} containing all activities a specified {@code Person} + * has participated in, for GUI purposes. + */ + Set getAssociatedActivities(Person person); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 59ed78712af..70aab2d9565 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -6,8 +6,10 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Optional; +import java.util.Set; import java.util.function.Predicate; import java.util.logging.Logger; +import java.util.stream.Collectors; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; @@ -253,6 +255,26 @@ public void updateFilteredActivityList(Predicate predicate) { filteredActivities.setPredicate(predicate); } + // =========== Association lookup accessors for GUI ============================================ + + @Override + public Set getAssociatedPersons(Activity activity) { + requireNonNull(activity); + + return this.addressBook.getPersonList().stream() + .filter((person) -> activity.hasPerson(person.getPrimaryKey())) + .collect(Collectors.toUnmodifiableSet()); + } + + @Override + public Set getAssociatedActivities(Person person) { + requireNonNull(person); + + return this.activityBook.getActivityList().stream() + .filter((activity) -> activity.hasPerson(person.getPrimaryKey())) + .collect(Collectors.toUnmodifiableSet()); + } + // =========== Overridden Java methods ========================================================= @Override @@ -277,5 +299,4 @@ public boolean equals(Object obj) { && filteredPersons.equals(other.filteredPersons) && filteredActivities.equals(other.filteredActivities); } - } diff --git a/src/main/java/seedu/address/ui/ActivityDetailsPanel.java b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java index debf41459f5..c67dd96d14b 100644 --- a/src/main/java/seedu/address/ui/ActivityDetailsPanel.java +++ b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java @@ -1,11 +1,14 @@ package seedu.address.ui; +import java.util.Set; + import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.FlowPane; import javafx.scene.layout.Region; import seedu.address.model.activity.Activity; +import seedu.address.model.person.Person; /** * Panel displaying details of a contact. @@ -28,7 +31,7 @@ public class ActivityDetailsPanel extends UiPart { @FXML private Label spending; - public ActivityDetailsPanel(Activity viewedActivity) { + public ActivityDetailsPanel(Activity viewedActivity, Set participants) { super(FXML); this.activity = viewedActivity; diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 21b5fb061cd..a24f2d82583 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import java.util.Optional; +import java.util.Set; import java.util.logging.Logger; import javafx.fxml.FXML; @@ -16,6 +17,8 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Context; import seedu.address.model.ContextType; +import seedu.address.model.activity.Activity; +import seedu.address.model.person.Person; /** * The Main Window. Provides the basic application layout containing a status @@ -159,11 +162,15 @@ private void contextSwitch(Context newContext) { contentContainer.getChildren().add(personListPanel.getRoot()); break; case VIEW_CONTACT: - personDetailsPanel = new PersonDetailsPanel(newContext.getContact().get()); + Person viewedContact = newContext.getContact().get(); + Set associatedActivities = logic.getAssociatedActivities(viewedContact); + personDetailsPanel = new PersonDetailsPanel(viewedContact, associatedActivities); contentContainer.getChildren().add(personDetailsPanel.getRoot()); break; case VIEW_ACTIVITY: - activityDetailsPanel = new ActivityDetailsPanel(newContext.getActivity().get()); + Activity viewedActivity = newContext.getActivity().get(); + Set associatedPersons = logic.getAssociatedPersons(viewedActivity); + activityDetailsPanel = new ActivityDetailsPanel(viewedActivity, associatedPersons); contentContainer.getChildren().add(activityDetailsPanel.getRoot()); break; default: diff --git a/src/main/java/seedu/address/ui/PersonDetailsPanel.java b/src/main/java/seedu/address/ui/PersonDetailsPanel.java index 9f8fd4ad919..eeda12bcca0 100644 --- a/src/main/java/seedu/address/ui/PersonDetailsPanel.java +++ b/src/main/java/seedu/address/ui/PersonDetailsPanel.java @@ -1,12 +1,14 @@ package seedu.address.ui; import java.util.Comparator; +import java.util.Set; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.FlowPane; import javafx.scene.layout.Region; +import seedu.address.model.activity.Activity; import seedu.address.model.person.Person; /** @@ -32,7 +34,7 @@ public class PersonDetailsPanel extends UiPart { @FXML private FlowPane tags; - public PersonDetailsPanel(Person viewedPerson) { + public PersonDetailsPanel(Person viewedPerson, Set activities) { super(FXML); this.person = viewedPerson; diff --git a/src/test/java/seedu/address/stub/ModelStub.java b/src/test/java/seedu/address/stub/ModelStub.java index 705d6d96061..bc7bf9709e2 100644 --- a/src/test/java/seedu/address/stub/ModelStub.java +++ b/src/test/java/seedu/address/stub/ModelStub.java @@ -3,6 +3,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Optional; +import java.util.Set; import java.util.function.Predicate; import javafx.collections.ObservableList; @@ -170,4 +171,14 @@ public ObservableList getFilteredActivityList() { public void updateFilteredActivityList(Predicate predicate) { throw new AssertionError("This method (updateFilteredActivityList) should not be called."); } + + @Override + public Set getAssociatedPersons(Activity activity) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Set getAssociatedActivities(Person person) { + throw new AssertionError("This method should not be called."); + } } From d19a79a19fb5d455b61ab7f641529a7ff9c8ffb9 Mon Sep 17 00:00:00 2001 From: Aulud <44989315+Aulud@users.noreply.github.com> Date: Tue, 29 Oct 2019 05:47:36 +0800 Subject: [PATCH 09/13] Update ActivityDetailsPanel to display all participants of an Activity --- .../java/seedu/address/ui/ActivityCard.java | 1 + .../address/ui/ActivityDetailsPanel.java | 6 ++- .../resources/view/ActivityDetailsPanel.fxml | 2 +- src/main/resources/view/LightTheme.css | 50 +++++++++++++------ 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/address/ui/ActivityCard.java b/src/main/java/seedu/address/ui/ActivityCard.java index c9e4b8d83ed..43d06bb3886 100644 --- a/src/main/java/seedu/address/ui/ActivityCard.java +++ b/src/main/java/seedu/address/ui/ActivityCard.java @@ -40,6 +40,7 @@ public ActivityCard(Activity activity, int displayedIndex) { id.setText("ID: " + activity.getPrimaryKey()); index.setText("#" + displayedIndex); title.setText(activity.getTitle().toString()); + int numParticipants = activity.getParticipantIds().size(); participantCount.setText(numParticipants + (numParticipants != 1 ? " participants" : " participant")); } diff --git a/src/main/java/seedu/address/ui/ActivityDetailsPanel.java b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java index c67dd96d14b..34f878cb9c4 100644 --- a/src/main/java/seedu/address/ui/ActivityDetailsPanel.java +++ b/src/main/java/seedu/address/ui/ActivityDetailsPanel.java @@ -25,7 +25,7 @@ public class ActivityDetailsPanel extends UiPart { @FXML private Label title; @FXML - private FlowPane participants; + private FlowPane participantTags; @FXML private Label participantCount; @FXML @@ -38,6 +38,10 @@ public ActivityDetailsPanel(Activity viewedActivity, Set participants) { id.setText("ID: " + activity.getPrimaryKey()); title.setText(activity.getTitle().toString()); + participants.stream() + .map((participant) -> participant.getName().toString()) + .forEach(name -> participantTags.getChildren().add(new Label(name))); + int numParticipants = activity.getParticipantIds().size(); participantCount.setText(numParticipants + (numParticipants != 1 ? " participants" : " participant")); diff --git a/src/main/resources/view/ActivityDetailsPanel.fxml b/src/main/resources/view/ActivityDetailsPanel.fxml index 16d40c2ae27..ab407a3a9d6 100644 --- a/src/main/resources/view/ActivityDetailsPanel.fxml +++ b/src/main/resources/view/ActivityDetailsPanel.fxml @@ -27,13 +27,13 @@ - + - + diff --git a/src/main/resources/view/ExpenseCard.fxml b/src/main/resources/view/ExpenseCard.fxml index 6a402e37b1e..74a397ed118 100644 --- a/src/main/resources/view/ExpenseCard.fxml +++ b/src/main/resources/view/ExpenseCard.fxml @@ -7,21 +7,22 @@ - - - + + - + - - - + diff --git a/src/main/resources/view/LightTheme.css b/src/main/resources/view/LightTheme.css index f442a7d628b..1af1987479d 100644 --- a/src/main/resources/view/LightTheme.css +++ b/src/main/resources/view/LightTheme.css @@ -127,7 +127,8 @@ -fx-focus-color: transparent; } -.person-details, .activity-details { +.person-details, .activity-details, +.history-container .expense-history { /* Add horizontal divider to visually separate details of contact from activity listings */ -fx-border-color: linear-gradient(from 0% 0% to 100% 0%, #dbdbdb, #ababab, #dbdbdb); -fx-border-width: 0 0 2px 0; @@ -151,7 +152,7 @@ .person-details .tag-list, .activity-details .activity-title, .activity-details .activity-participant-count-container, -.activity-details .participant-list { +.activity-details .participant-list, .history-container .expense-history { -fx-padding: 0 0 4 0; } @@ -170,16 +171,17 @@ -fx-text-alignment: center; } -.history-container { +.history-container, .transfers-container { -fx-padding: 4 2 0 2; -fx-alignment: center; } -.history-container .activity-history, .history-container .expense-history { +.history-container .activity-history { -fx-padding: 0 0 8 0; } -.history-container .activity-history-header, .history-container .expense-history-header { +.history-container .activity-history-header, .history-container .expense-history-header, +.transfers-container .activity-transfers-header { -fx-padding: 2 8 2 8; -fx-background-color: #cbcbcb; -fx-border-color: #c0c0c0; @@ -189,7 +191,8 @@ -fx-text-alignment: center; } -.activity-history-card, .expense-card { +.activity-history-card, .expense-card, .transfer-card { + -fx-padding: 4 0 4 0; -fx-border-color: #c0c0c0; -fx-border-radius: 1px; -fx-border-width: 2px; @@ -223,7 +226,8 @@ } .activity-details .participant-list .label, -.expense-card .expense-sharing-list .label { +.expense-card .expense-sharing-list .label, +.transfer-card .transfer-from, .transfer-card .transfer-to { -fx-background-color: royalblue; -fx-padding: 2 4 2 4; -fx-border-radius: 2; @@ -241,13 +245,39 @@ -fx-text-alignment: center; } -.expense-card .expense-sharing-list .label { +.expense-card .expense-sharing-list .label, +.transfer-card .transfer-from { -fx-background-color: maroon; -fx-font-size: 10px; } -.expense-card .expense-sharing-list .expense-owner { +.expense-card .expense-sharing-list .expense-owner, +.transfer-card .transfer-to { -fx-background-color: darkgreen; + -fx-font-size: 10px; +} + +.expense-card .expense-owner { + -fx-text-alignment: center; +} + +.transfer-card .transfer-from-container, .transfer-card .transfer-to-container { + -fx-padding: 0 4 0 4; +} + +.transfer-card .transfer-amt-container { + -fx-padding: 0 4 4 4; +} + +.transfer-card .transfer-amount { + -fx-font-family: "Noto Sans CJK SC Bold", "Segoe UI", sans-serif; + -fx-font-weight: bold; + -fx-font-size: 14px; + -fx-text-alignment: center; +} + +.transfer-card .label { + -fx-text-alignment: center; } /* diff --git a/src/main/resources/view/PersonDetailsPanel.fxml b/src/main/resources/view/PersonDetailsPanel.fxml index 58a0cc50319..6423dfe7b0d 100644 --- a/src/main/resources/view/PersonDetailsPanel.fxml +++ b/src/main/resources/view/PersonDetailsPanel.fxml @@ -10,7 +10,7 @@ - @@ -50,7 +50,7 @@ diff --git a/src/main/resources/view/TransferCard.fxml b/src/main/resources/view/TransferCard.fxml new file mode 100644 index 00000000000..e750be3c0ec --- /dev/null +++ b/src/main/resources/view/TransferCard.fxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +