diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 0f268725c7a..014d3500a1b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -219,6 +219,48 @@ Pros: Arguably a more OOP approach since all commands that trigger view IS-A `Vi Cons: You cannot implement any command that does not involve viewing but inherits from any command that is a children of `ViewCommand`. An example could be trying to create identical commands that does not toggle the UI after execution. This would require duplication of the exact same command code but inheriting from `Command` instead of `ViewCommand`. + +### Search feature + +#### Implementation + +The search feature is implemented using the `SearchCommand` class. It extends `Command` and overrides the `execute()` method to +filter users by the specified parameters. + +The search parameters from the user input are parsed using the parse method in the `SearchCommandParser` class. `SearchCommandParser::Parse` +takes in the search parameters from the user input and combines them into a list of predicates. This list of predicates is then +passed as an argument to the `SearchCommand` constructor and the method returns a `SearchCommand` instance with the associated list of predicates. + +Currently, the search parameters could belong to any of the three following categories: `Name`, `Status`, and `Tag`. Prefixes +`n/`, `st/` and `t/` are used to denote the category of the search parameters respectively. E.g. `search n/alex st/interviewed t/swe` + +The list of predicates is a list comprising predicate objects whose classes implement the `Predicate` class in Java. +Each category has its own predicate class i.e. `NameContainsKeywordPredicate`, `StatusContainsKeywordPredicate`, `TagContainsKeywordPredicate` +and each class overrides the `test` method which returns true if the persons list contains any of the given names/status/tags. + +Finally, the execute method in `SearchCommand` class invokes the `updateFilteredPersonList(predicatesList)` which will +update the list of persons displayed. + +Given below is an example usage scenario and how the search mechanism behaves at each step. + +Step 1. The user launches the application. + +Step 2. The user executes `search n/john st/offered t/swe` command to filter candidates having the name john, +offered status and tagged as swe. + +The following sequence diagram shows how the search operation works: + +**Note:** The lifeline for `SearchCommand` and `SearchCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. + + + +Step 3. The user should see the UI below upon entering `search n/john st/interviewed t/friends`. + +![View](images/search.png) + +**Note:** The current implementation of search allows users to search by any of the categories individually or by different combinations of the categories. +It also allows users to specify more than one search parameter for each category e.g. `search n/alex bernice` + ### \[Proposed\] Undo/redo feature #### Proposed Implementation @@ -432,31 +474,16 @@ Use case ends. * 2b1. JABPro shows a message indicating that there are no persons to display. Use case ends. -**Use case: Search a person by name** +**Use case: Search persons by the specified categories(name, status and/ tag)** **MSS** -1. Hiring manager types in name keywords to search users by name. -2. JABPro shows a list of persons whose names contain matching keywords. - Use case ends. - -**Extensions** - -* 1a. The given name keyword is invalid (invalid name). - * 1a1. JABPro shows an error message. - Use case resumes at step 1. -* 2a. The list is empty. - Use case ends. - -**Use case: Search a person by application status** - -**MSS** -1. User keys in search command with application status (i.e. interviewed, pending, rejected, offered). -2. JABPro shows a list of persons whose status match the given status keywords. - Use case ends. +1. Hiring manager types in search parameters to search users by the specified categories. +2. JABPro shows a list of persons whose profile matches the given parameters. +Use case ends. **Extensions** -* 1a. The given name status is invalid (not from the given list of valid status keywords). +* 1a. The given name/status/tag parameter is invalid. * 1a1. JABPro shows an error message. Use case resumes at step 1. * 2a. The list is empty. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b03f8a194cb..c1b8b5b4bae 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -62,6 +62,9 @@ JobApplicationsBook Pro (JABPro) is a **desktop app for hiring managers of compa * Items in square brackets are optional.
e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. +* When using parentheses ( ) with items separated by the pipe symbol |, at least one item must be included.
+ e.g in the command `search (n/KEYWORD [MORE KEYWORDS] | st/KEYWORD [MORE KEYWORDS] | t/KEYWORD [MORE KEYWORDS])`, it is necessary to specify at least one search category. + * Items with `…`​ after them can be used multiple times including zero times.
e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. @@ -196,7 +199,9 @@ Examples: ### Search job applicants by category: `search` -Finds job applicants whose profiles match the specified categories' keywords. The search categories are: name, status +Finds job applicants whose profiles match the specified categories' keywords. The search categories are: name, status, tag. + +Format: `search (n/KEYWORD [MORE KEYWORDS] | st/KEYWORD [MORE KEYWORDS] | t/KEYWORD [MORE KEYWORDS])` #### Search job applicants by name @@ -219,24 +224,36 @@ Examples: Finds job applicants whose status match any of the given keywords -Format: `search s/KEYWORD [MORE KEYWORDS]` +Format: `search st/KEYWORD [MORE KEYWORDS]` + +* Keywords can only be from the following list: `Preliminary`, `Interviewed`, `Rejected`, `Offered` + e.g. `search st/interviewing` will give an error. +* Keywords are case-insensitive: `search st/interviewed` and `search st/INTERVIEWED` return the same result. + +Example: +* `search st/interviewed` + +#### Search job applicants by tag + +Finds job applicants whose tag(s) match any of the given tag keywords + +Format: `search t/KEYWORD [MORE KEYWORDS]` -* Keywords can only be from the following list: `Pending`, `Interviewed`, `Rejected`, `Offered` - e.g. `search s/interviewing` will give an error. -* Keywords are case-insensitive: `search s/interviewd` and `search s/INTERVIEWED` return the same result. +* Keywords are case-insensitive: `search t/hardworking' and `search t/HARDWORKING` return the same result. Example: -* `search s/interviewed` +* `search t/hardworking` #### Notes for advanced users: -* You can combine the name and status search categories (e.g. `search n/Alex s/offered`) in a single search command. +* You can combine the search categories (e.g. `search n/Alex st/offered t/software engineer`) in a single search command. * Each search category can be used at most once in a single search command - e.g. `search n/Alex n/Adam s/rejected` is not allowed. + e.g. `search n/Alex n/Adam st/rejected` is not allowed. Example: -* `search n/Alex Bernice s/interviewed rejected` will output applicants whose: +* `search n/Alex Bernice st/interviewed rejected t/analyst` will output applicants whose: * names contain either Alex `or` Bernice * `and` status is either interviewed `or` rejected. + * `and` has a tag `analyst` ### Deleting a person : `delete` @@ -354,7 +371,7 @@ Action | Format, Examples **Delete** | `delete INDEX`
e.g., `delete 3` **Set** | `set INDEX STATUS`
e.g., `set 2 Interviewed` **Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit 2 n/James Lee e/jameslee@example.com` -**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` +**Search** | `search (n/KEYWORD [MORE KEYWORDS] | st/KEYWORD [MORE KEYWORDS] | t/KEYWORD [MORE KEYWORDS])`
e.g., `search n/alex st/interviewed` **List** | `list s/ATTRIBUTE`
e.g. `list s/name` **Export** | `export` **Help** | `help` diff --git a/docs/diagrams/SearchSequenceDiagram.puml b/docs/diagrams/SearchSequenceDiagram.puml new file mode 100644 index 00000000000..37f57208496 --- /dev/null +++ b/docs/diagrams/SearchSequenceDiagram.puml @@ -0,0 +1,76 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":SearchCommandParser" as SearchCommandParser LOGIC_COLOR +participant "f:SearchCommand" as SearchCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute("search st/offered") +activate LogicManager + +LogicManager -> AddressBookParser : parseCommand("search st/offered") +activate AddressBookParser + +create SearchCommandParser +AddressBookParser -> SearchCommandParser +activate SearchCommandParser + +SearchCommandParser --> AddressBookParser +deactivate SearchCommandParser + +AddressBookParser -> SearchCommandParser : parse("search st/offered") +activate SearchCommandParser + +create SearchCommand +SearchCommandParser -> SearchCommand : searchCommand(predicatesList) +activate SearchCommand + +SearchCommand --> SearchCommandParser : f +deactivate SearchCommand + +SearchCommandParser --> AddressBookParser : f +deactivate SearchCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +SearchCommandParser -[hidden]-> AddressBookParser +destroy SearchCommandParser + +AddressBookParser --> LogicManager : f +deactivate AddressBookParser + +LogicManager -> SearchCommand : execute() +activate SearchCommand + +SearchCommand -> Model : updateFilteredPersonList(predicatesList) +activate Model + +Model --> SearchCommand +deactivate Model + +create CommandResult +SearchCommand -> CommandResult +activate CommandResult + +CommandResult --> SearchCommand +deactivate CommandResult + +SearchCommand --> LogicManager : result +deactivate SearchCommand + + + +[<--LogicManager +deactivate LogicManager + + + +@enduml diff --git a/docs/images/search.png b/docs/images/search.png new file mode 100644 index 00000000000..6a8c8208602 Binary files /dev/null and b/docs/images/search.png differ