Skip to content

Commit

Permalink
Merge pull request nus-cs2103-AY2223S1#86 from ShenyiCui/Shenyi/67-cr…
Browse files Browse the repository at this point in the history
…eate-select-contact-and-ui

Feat: Add select contact command and UI
  • Loading branch information
jasonqiu212 authored Oct 23, 2022
2 parents 6d00267 + a9bdf27 commit c47d1e2
Show file tree
Hide file tree
Showing 39 changed files with 690 additions and 31 deletions.
10 changes: 10 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
coverage:
status:
patch:
default:
target: auto
threshold: 50%
project:
default:
target: auto
threshold: 75%
2 changes: 1 addition & 1 deletion docs/tutorials/AddRemark.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ save it with `Model#setPerson()`.
personToEdit.getAddress(), remark, personToEdit.getTags());

model.setPerson(personToEdit, editedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PEOPLE);

return new CommandResult(generateSuccessMessage(editedPerson));
}
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/TracingCode.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
throw new CommandException(MESSAGE_DUPLICATE_PERSON);
}
model.setPerson(personToEdit, editedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PEOPLE);
return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
}
```
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/swift/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
initialData = new AddressBook();
}

return new ModelManager(initialData, userPrefs);
ModelManager newModelManager = new ModelManager(initialData, userPrefs);
// Hide all Tasks by Default
newModelManager.updateFilteredTaskList(Model.PREDICATE_HIDE_ALL_TASKS);
return newModelManager;
}

private void initLogging(Config config) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/swift/commons/core/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ public class Messages {
public static final String MESSAGE_INVALID_TASK_DISPLAYED_INDEX = "The task index provided is invalid";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_TASKS_LISTED_OVERVIEW = "%1$d tasks listed!";
public static final String MESSAGE_PERSONS_SELECTED_OVERVIEW = "Person Selected!";
}
4 changes: 4 additions & 0 deletions src/main/java/swift/logic/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import swift.logic.parser.exceptions.ParseException;
import swift.model.ReadOnlyAddressBook;
import swift.model.person.Person;
import swift.model.task.Task;

/**
* API of the Logic component
Expand All @@ -33,6 +34,9 @@ public interface Logic {
/** Returns an unmodifiable view of the filtered list of persons */
ObservableList<Person> getFilteredPersonList();

/** Returns an unmodifiable view of the filtered list of tasks */
ObservableList<Task> getFilteredTaskList();

/**
* Returns the user prefs' address book file path.
*/
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/swift/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
import swift.model.Model;
import swift.model.ReadOnlyAddressBook;
import swift.model.person.Person;
import swift.model.task.Task;
import swift.storage.Storage;

/**
* The main LogicManager of the app.
*/
public class LogicManager implements Logic {

public static final String FILE_OPS_ERROR_MESSAGE = "Could not save data to file: ";
private final Logger logger = LogsCenter.getLogger(LogicManager.class);

Expand Down Expand Up @@ -64,6 +66,11 @@ public ObservableList<Person> getFilteredPersonList() {
return model.getFilteredPersonList();
}

@Override
public ObservableList<Task> getFilteredTaskList() {
return model.getFilteredTaskList();
}

@Override
public Path getAddressBookFilePath() {
return model.getAddressBookFilePath();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/swift/logic/commands/AddTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public CommandResult execute(Model model) throws CommandException {
model.addBridge(model.getFilteredPersonList().get(index.getZeroBased()), toAdd);
}

model.hotUpdateAssociatedContacts();

return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/swift/logic/commands/DeleteTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public CommandResult execute(Model model) throws CommandException {

Task taskToDelete = lastShownList.get(targetIndex.getZeroBased());
model.deleteTask(taskToDelete);
model.hotUpdateAssociatedContacts();
return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete));
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/swift/logic/commands/EditContactCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import static swift.logic.parser.CliSyntax.PREFIX_NAME;
import static swift.logic.parser.CliSyntax.PREFIX_PHONE;
import static swift.logic.parser.CliSyntax.PREFIX_TAG;
import static swift.model.Model.PREDICATE_SHOW_ALL_PERSONS;
import static swift.model.Model.PREDICATE_SHOW_ALL_PEOPLE;

import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -83,7 +83,7 @@ public CommandResult execute(Model model) throws CommandException {
}

model.setPerson(personToEdit, editedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PEOPLE);
return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/swift/logic/commands/EditTaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public CommandResult execute(Model model) throws CommandException {

model.setTask(taskToEdit, editedTask);
model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
model.hotUpdateAssociatedContacts();
return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, editedTask));
}

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/swift/logic/commands/ListContactCommand.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package swift.logic.commands;

import static java.util.Objects.requireNonNull;
import static swift.model.Model.PREDICATE_SHOW_ALL_PERSONS;
import static swift.model.Model.PREDICATE_SHOW_ALL_PEOPLE;

import swift.model.Model;

Expand All @@ -18,7 +18,8 @@ public class ListContactCommand extends Command {
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredTaskList(Model.PREDICATE_HIDE_ALL_TASKS);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PEOPLE);
return new CommandResult(MESSAGE_SUCCESS);
}
}
2 changes: 2 additions & 0 deletions src/main/java/swift/logic/commands/ListTaskCommand.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package swift.logic.commands;

import static java.util.Objects.requireNonNull;
import static swift.model.Model.PREDICATE_HIDE_ALL_PEOPLE;
import static swift.model.Model.PREDICATE_SHOW_ALL_TASKS;

import swift.commons.core.Messages;
Expand All @@ -22,6 +23,7 @@ public class ListTaskCommand extends Command {
@Override
public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredPersonList(PREDICATE_HIDE_ALL_PEOPLE);
model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
return new CommandResult(
String.format(Messages.MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
Expand Down
73 changes: 73 additions & 0 deletions src/main/java/swift/logic/commands/SelectContactCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package swift.logic.commands;

import static java.util.Objects.requireNonNull;
import static swift.model.Model.PREDICATE_SHOW_ALL_BRIDGE;
import static swift.model.Model.PREDICATE_SHOW_ALL_TASKS;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import swift.commons.core.Messages;
import swift.commons.core.index.Index;
import swift.logic.commands.exceptions.CommandException;
import swift.model.Model;
import swift.model.bridge.PersonTaskBridge;
import swift.model.person.Person;
import swift.model.task.Task;

/**
* Deletes a task identified using it's displayed index from the address book.
*/
public class SelectContactCommand extends Command {

public static final String COMMAND_WORD = "select_contact";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Selects the contact identified by the index number used in the displayed contact list.\n"
+ "Parameters: INDEX (must be a positive integer)\n"
+ "Example: " + COMMAND_WORD + " 1";

public static final String MESSAGE_SELECT_CONTACT_SUCCESS = "Person Selected!";

private final Index targetIndex;

public SelectContactCommand(Index targetIndex) {
this.targetIndex = targetIndex;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List<Person> lastShownPersonList = model.getFilteredPersonList();

if (targetIndex.getZeroBased() >= lastShownPersonList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

Person selectedPerson = lastShownPersonList.get(targetIndex.getZeroBased());
model.updateFilteredPersonList((person) -> person.equals(selectedPerson));

model.updateFilteredBridgeList(PREDICATE_SHOW_ALL_BRIDGE);
model.updateFilteredBridgeList((bridge) -> bridge.getPersonId().equals(selectedPerson.getId()));
List<PersonTaskBridge> bridgeList = model.getFilteredBridgeList();

// Predicate to check whether task exists within a bridgeList
Predicate<Task> isTaskExist = (task) -> bridgeList.stream()
.filter((bridge) -> bridge.getTaskId().equals(task.getId()))
.collect(Collectors.toList())
.size() != 0;

model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
model.updateFilteredTaskList(isTaskExist);

return new CommandResult(Messages.MESSAGE_PERSONS_SELECTED_OVERVIEW);
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof SelectContactCommand // instanceof handles nulls
&& targetIndex.equals(((SelectContactCommand) other).targetIndex)); // state check
}
}
3 changes: 3 additions & 0 deletions src/main/java/swift/logic/parser/AddressBookParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import swift.logic.commands.HelpCommand;
import swift.logic.commands.ListContactCommand;
import swift.logic.commands.ListTaskCommand;
import swift.logic.commands.SelectContactCommand;
import swift.logic.parser.exceptions.ParseException;

/**
Expand Down Expand Up @@ -59,6 +60,8 @@ public Command parseCommand(String userInput) throws ParseException {
return new ClearCommand();
case FindContactCommand.COMMAND_WORD:
return new FindContactCommandParser().parse(arguments);
case SelectContactCommand.COMMAND_WORD:
return new SelectContactCommandParser().parse(arguments);
case ListContactCommand.COMMAND_WORD:
return new ListContactCommand();
case ListTaskCommand.COMMAND_WORD:
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/swift/logic/parser/SelectContactCommandParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package swift.logic.parser;

import static swift.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import swift.commons.core.index.Index;
import swift.logic.commands.SelectContactCommand;
import swift.logic.parser.exceptions.ParseException;

/**
* Parses input arguments and creates a new DeleteCommand object
*/
public class SelectContactCommandParser implements Parser<SelectContactCommand> {

/**
* Parses the given {@code String} of arguments in the context of the DeleteCommand
* and returns a DeleteCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public SelectContactCommand parse(String args) throws ParseException {
try {
Index index = ParserUtil.parseIndex(args);
return new SelectContactCommand(index);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, SelectContactCommand.MESSAGE_USAGE), pe);
}
}

}
6 changes: 4 additions & 2 deletions src/main/java/swift/model/AddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,13 @@ public ObservableList<PersonTaskBridge> getBridgeList() {
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof AddressBook // instanceof handles nulls
&& persons.equals(((AddressBook) other).persons));
&& persons.equals(((AddressBook) other).persons))
&& tasks.equals(((AddressBook) other).tasks)
&& bridges.equals(((AddressBook) other).bridges);
}

@Override
public int hashCode() {
return persons.hashCode() ^ tasks.hashCode();
return persons.hashCode() ^ tasks.hashCode() ^ bridges.hashCode();
}
}
22 changes: 21 additions & 1 deletion src/main/java/swift/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javafx.collections.ObservableList;
import swift.commons.core.GuiSettings;
import swift.logic.commands.exceptions.CommandException;
import swift.model.bridge.PersonTaskBridge;
import swift.model.person.Person;
import swift.model.task.Task;
Expand All @@ -14,8 +15,11 @@
*/
public interface Model {
/** {@code Predicate} that always evaluate to true */
Predicate<Person> PREDICATE_SHOW_ALL_PERSONS = unused -> true;
Predicate<Person> PREDICATE_SHOW_ALL_PEOPLE = unused -> true;
Predicate<Person> PREDICATE_HIDE_ALL_PEOPLE = unused -> false;
Predicate<Task> PREDICATE_SHOW_ALL_TASKS = unused -> true;
Predicate<Task> PREDICATE_HIDE_ALL_TASKS = unused -> false;
Predicate<PersonTaskBridge> PREDICATE_SHOW_ALL_BRIDGE = unused -> true;

/**
* Replaces user prefs data with the data in {@code userPrefs}.
Expand Down Expand Up @@ -47,6 +51,13 @@ public interface Model {
*/
void setAddressBookFilePath(Path addressBookFilePath);

/**
* Method that updates the associated contact list if it's unambiguous that a user has been selected.
*
* @throws CommandException
*/
void hotUpdateAssociatedContacts() throws CommandException;

/**
* Replaces address book data with the data in {@code addressBook}.
*/
Expand Down Expand Up @@ -91,6 +102,15 @@ public interface Model {
/** Returns an unmodifiable view of the filtered task list */
ObservableList<Task> getFilteredTaskList();

/**
* Updates the filter of the filtered person list to filter by the given {@code predicate}.
* @throws NullPointerException if {@code predicate} is null.
*/
void updateFilteredBridgeList(Predicate<PersonTaskBridge> predicate);

/** Returns an unmodifiable view of the filtered task list */
ObservableList<PersonTaskBridge> getFilteredBridgeList();

/**
* Updates the filter of the filtered task list to filter by the given {@code predicate}.
* @throws NullPointerException if {@code predicate} is null.
Expand Down
Loading

0 comments on commit c47d1e2

Please sign in to comment.