Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated List Command and User Guide #82

Merged
merged 15 commits into from Oct 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/DeveloperGuide.adoc
Expand Up @@ -359,6 +359,52 @@ Implementation of this additional feature would require changes to both `InviteC


// tag::dataencryption[]

=== List Feature

==== Current Implementation

The `list` feature allows users to filter through all the individual people in ProManage and understand which department
they are from. The command currently has 2 sub-features; `list all` and `list dep DEPARTMENT`. The user can list all the
people in ProManage by simply typing `list all`. Alternatively, the user can filter through ProManage and get the
relevant Person's information by listing those of the relevant department. The user can list multiple departments such
as `list dep Admin Finance`. As of now, each person can only be inside one department.

The listing of people from the respective departments is facilitated by the class: `Departments`,
a list of departments of type `String`.

The following is a more detailed description of the classes involved:

* `Department`
** Each `Person` object has a `Department`, which is the department in which the person is in.
** This class is essentially another piece of information about the person.
** Each `Person` can only be in one `Department`.

==== Execution of Command

Given below is an example usage scenario and how the list mechanism works.

Step 1. The user executes `list dep Admin` to list only the people in the Admin department. The command text is passed
to an instance of the `LogicManager` class.

Step 2. The `LogicManager` instance calls `AddressBookParser#parsecommand`, which parses the `list` command prefix
"list".

Step 3. `ListCommandParser#parse` parses the type of command that is called upon and if applicable, the departments
listed. The list command can take in either `all` or `dep`. `all` means that are no predicates and 'dep' means specific
departments are about to be listed. An instance of the `ListCommand` encapsulating the type of `ListCommand` and if
applicable, the predicates involved, is then returned to `Logic Manager`.

Step 4. `Logic Manager` then executes this `ListCommand` by calling `ListCommand#execute`.

Step 5. The filtered person list is first obtained by calling `PersonModel#updateFilteredPersonList`. Based on the departments, the list of `Person` are selected.

Step 9. The `ListCommand#execute` finally returns a `CommandResult` with a success message.

The sequence diagram below illustrates the execution of the `invite` command.

image::ListSequenceDiagram.png[width="800"]

=== [Proposed] Data Encryption

_{Explain here how the data encryption feature will be implemented}_
Expand Down
30 changes: 20 additions & 10 deletions docs/UserGuide.adoc
Expand Up @@ -103,7 +103,23 @@ An employee can have any number of tags (including 0)
Example: +
`add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 dep/ADMIN`

=== Editing an employee : `edit`
=== Listing all personnel of the company : 'list'

Shows a list of all the personnel, all the events, or those people in the specific department in the project team +
Format/Prompts: +

Enter command to list all people: `list all people` +
Enter a command to list all the events: `list all events` +
Enter a command to list all people and events: `list all` +
Enter a command to list people in the specific `DEPARTMENT`: `list dep DEPARTMENT`

Example: +
`list dep Admin` +
`list dep Admin Finance`


=== Editing an employee : 'edit'

Priority level: `default`,`manager`

Edits the details of the employee: +
Expand Down Expand Up @@ -133,13 +149,6 @@ Enter a command: `delete PERSON_INDEX`
* The index *must be a positive integer* 1, 2, 3, ...
****

=== Listing all employee of the company : `list`
Priority level: all

Shows a list of employee in the company +
Format/Prompts: +
Enter a command: `list`

=== Adding an event: `addEvent`
Priority level: `default`,`manager`

Expand Down Expand Up @@ -222,8 +231,8 @@ Format: sort `key word` +
Example: sort name

=== Invite employees: `invite`
Priority level: all

Priority level: all
Invites an employee to an event. +
Format: `invite PERSON_INDEX to/EVENT_INDEX` +
Example: invite 1 to/2
Expand Down Expand Up @@ -375,6 +384,7 @@ Enter a command: `exit`
ProManage data saves data in the hard disk automatically after any command that changes the data. +
There is no need to save manually.


== FAQ

*Q*: How do I transfer my data to another Computer? +
Expand All @@ -388,7 +398,7 @@ There is no need to save manually.

* *Delete* : `delete PERSON_INDEX`

* *List* : `list`
* *List* : `list all` OR `list all people` OR `list all events` or `list dep Admin`

* *addEvent* : `addEvent n/NAME d/DESCRIPTION l/LOCATION date/DATE s/START_TIME e/END_TIME`

Expand Down
Binary file added docs/diagrams/ListSequenceDiagram.pptx
Binary file not shown.
Binary file added docs/images/ListSequenceDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 60 additions & 6 deletions src/main/java/seedu/address/logic/commands/ListCommand.java
@@ -1,27 +1,81 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ALL_PEOPLE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_LIST_DEPARTMENT;
import static seedu.address.model.EventModel.PREDICATE_SHOW_ALL_EVENTS;
import static seedu.address.model.PersonModel.PREDICATE_SHOW_ALL_PERSONS;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;

import seedu.address.commons.core.Messages;
import seedu.address.logic.CommandHistory;
import seedu.address.model.Model;
import seedu.address.model.person.DepartmentContainsKeywordsPredicate;

/**
* Lists all persons in the address book to the user.
* Lists all persons in the address book to the user depending on the parameter.
*/
public class ListCommand extends Command {

public static final String COMMAND_WORD = "list";

public static final String MESSAGE_SUCCESS = "Listed all persons and events";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all persons by the given parameter\n"
+ "Parameters: "
+ PREFIX_LIST_DEPARTMENT + " DEPARTMENT "
+ "or " + PREFIX_ALL_PEOPLE + "\n"
+ "Example: " + COMMAND_WORD + " " + PREFIX_LIST_DEPARTMENT + " Admin";

public static final String MESSAGE_SUCCESS_PEOPLE = "All people listed!";
public static final String MESSAGE_SUCCESS_EVENT = "All events listed!";
public static final String MESSAGE_SUCCESS_ALL = "All people and events listed";

public static final String LIST_KEY_DEPARTMENT = "dep";
public static final String LIST_KEY_ALL = "all";
public static final String LIST_KEY_PEOPLE = "all people";
public static final String LIST_KEY_EVENT = "all events";

private final String listKey;
private final DepartmentContainsKeywordsPredicate predicate;

public ListCommand(String sortByParam, DepartmentContainsKeywordsPredicate predicate) {
requireNonNull(sortByParam);
//requireNonNull(predicate);
this.predicate = predicate;
listKey = sortByParam;
}

@Override
public CommandResult execute(Model model, CommandHistory history) {
requireNonNull(model);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS);
return new CommandResult(MESSAGE_SUCCESS);

String message = null;

switch (listKey) {
case (LIST_KEY_DEPARTMENT): model.updateFilteredPersonList(predicate);
return new CommandResult(
String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));

case (LIST_KEY_EVENT): model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS);
message = MESSAGE_SUCCESS_EVENT;
break;
case (LIST_KEY_PEOPLE): model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
message = MESSAGE_SUCCESS_PEOPLE;
break;
case (LIST_KEY_ALL): model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.updateFilteredEventList(PREDICATE_SHOW_ALL_EVENTS);
message = MESSAGE_SUCCESS_ALL;
break;
default:
}
return new CommandResult(message);


}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof ListCommand
&& ((predicate == null && ((ListCommand) other).predicate == null) // instanceof handles nulls
|| predicate.equals(((ListCommand) other).predicate)));
}
}
Expand Up @@ -82,7 +82,7 @@ public Command parseCommand(String userInput) throws ParseException {
return new FindCommandParser().parse(arguments);

case ListCommand.COMMAND_WORD:
return new ListCommand();
return new ListCommandParser().parse(arguments);

case SortCommand.COMMAND_WORD:
return new SortCommandParser().parse(arguments);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/seedu/address/logic/parser/CliSyntax.java
Expand Up @@ -18,8 +18,11 @@ public class CliSyntax {
public static final Prefix PREFIX_END_DATE = new Prefix("e/");
public static final Prefix PREFIX_DESCRIPTION = new Prefix("d/");
public static final Prefix PREFIX_DEPARTMENT = new Prefix("dep/");
public static final Prefix PREFIX_LIST_DEPARTMENT = new Prefix("dep");
public static final Prefix PREFIX_LOCATION = new Prefix("l/");
public static final Prefix PREFIX_TO = new Prefix("to/");
public static final Prefix PREFIX_ALL_PEOPLE = new Prefix("all people");
public static final Prefix PREFIX_ALL_EVENTS = new Prefix("all events");
public static final Prefix PREFIX_FROM = new Prefix("from/");


Expand Down
Expand Up @@ -79,7 +79,7 @@ public Command parseCommand(String userInput) throws ParseException {
return new FindCommandParser().parse(arguments);

case ListCommand.COMMAND_WORD:
return new ListCommand();
return new ListCommandParser().parse(arguments);

case SortCommand.COMMAND_WORD:
return new SortCommandParser().parse(arguments);
Expand Down
Expand Up @@ -53,7 +53,7 @@ public Command parseCommand(String userInput) throws ParseException {
return new FindCommandParser().parse(arguments);

case ListCommand.COMMAND_WORD:
return new ListCommand();
return new ListCommandParser().parse(arguments);

case SortCommand.COMMAND_WORD:
return new SortCommandParser().parse(arguments);
Expand Down
87 changes: 87 additions & 0 deletions src/main/java/seedu/address/logic/parser/ListCommandParser.java
@@ -0,0 +1,87 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.DepartmentContainsKeywordsPredicate;

/**
* Parses input arguments and creates a new ListCommand object
*/
public class ListCommandParser implements Parser<ListCommand> {

/**
* Parses the given {@code String} of arguments in the context of the ListCommand
* and returns an ListCommand object for execution.
*
* @throws ParseException if the user input does not conform the expected format
*/
@Override
public ListCommand parse(String userInput) throws ParseException {
List<String> showAll = new ArrayList<>();
if (parseAll(userInput)) {
return new ListCommand(ListCommand.LIST_KEY_ALL, new DepartmentContainsKeywordsPredicate(showAll));
} else if (parsePeople(userInput)) {
return new ListCommand(ListCommand.LIST_KEY_PEOPLE, new DepartmentContainsKeywordsPredicate(showAll));
} else if (parseEvent(userInput)) {
return new ListCommand(ListCommand.LIST_KEY_EVENT, new DepartmentContainsKeywordsPredicate(showAll));
} else if (parseDep(userInput)) {
String relevantInfo = userInput.replaceAll("(?i)dep", "");

if (relevantInfo.equalsIgnoreCase(" ")) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
}
DepartmentContainsKeywordsPredicate predicate = preparePredicate(relevantInfo);
return new ListCommand(ListCommand.LIST_KEY_DEPARTMENT, predicate);
} else {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ListCommand.MESSAGE_USAGE));
}
}

/**
* Checks if first word of the userInput is equals to "all"
* @return boolean true if it is equal, if not, false
*/
private boolean parseAll(String userInput) {
return userInput.trim().equalsIgnoreCase("all");
}

/**
* Checks if first word of the userInput is equals to "all people"
* @return boolean true if it is equal, if not, false
*/
private boolean parsePeople(String userInput) {
return userInput.trim().equalsIgnoreCase("all people");
}

/**
* Checks if first word of the userInput is equals to "dep"
* @return boolean true if it is equal, if not, false
*/
private boolean parseDep(String userInput) {
return userInput.trim().split("\\s+")[0]
.equalsIgnoreCase("dep");
}

/**
* Checks if first word of the userInput is equals to "all events"
* @return boolean true if it is equal, if not, false
*/
private boolean parseEvent(String userInput) {
return userInput.trim().equalsIgnoreCase("all events");
}
/**
* Splits the userInput by whitespace and places it into a DepartmentContainsKeywordPredicate
* @return a new predicate
*/
private DepartmentContainsKeywordsPredicate preparePredicate(String userInput) {
String[] departments = userInput.trim().split("\\s+");
return new DepartmentContainsKeywordsPredicate(Arrays.asList(departments));
}

}
Expand Up @@ -78,7 +78,7 @@ public Command parseCommand(String userInput) throws ParseException {
return new FindCommandParser().parse(arguments);

case ListCommand.COMMAND_WORD:
return new ListCommand();
return new ListCommandParser().parse(arguments);

case SortCommand.COMMAND_WORD:
return new SortCommandParser().parse(arguments);
Expand Down
@@ -0,0 +1,33 @@
package seedu.address.model.person;

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

import seedu.address.commons.util.StringUtil;

/**
* Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
*/
public class DepartmentContainsKeywordsPredicate implements Predicate<Person> {
private final List<String> keywords;

public DepartmentContainsKeywordsPredicate(List<String> keywords) {
this.keywords = keywords; }

@Override
public boolean test(Person person) {
if (keywords.size() == 0) {
return true;
}
return keywords.stream()
.anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getDepartment().value, keyword));
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof DepartmentContainsKeywordsPredicate // instanceof handles nulls
&& keywords.equals(((DepartmentContainsKeywordsPredicate) other).keywords)); // state check
}

}