diff --git a/ImportInvalid.txt b/ImportInvalid.txt new file mode 100644 index 000000000000..bb8e09141c7b --- /dev/null +++ b/ImportInvalid.txt @@ -0,0 +1,19 @@ +John Doe +98765432 +johnd@example.com +311, Clementi Ave 2, #02-25 +owesMoney +friends + +Alex Neo +87438807 +alexyeoh@exampple.com +Blk 30 Geylang Street 29, #06-40 +family + +Berinice Yu +99272758 +berniceyu@example.com +Blk 30 Lorong 3 Serangoon Gardens, #07-18 +colleagues +friends diff --git a/ImportValid.xml b/ImportValid.xml new file mode 100644 index 000000000000..ddfe79175abb --- /dev/null +++ b/ImportValid.xml @@ -0,0 +1,30 @@ + + + + John Doe + 98765432 + johnd@example.com +
311, Clementi Ave 2, #02-25
+ owesMoney + friends +
+ + Alex Neo + 87438807 + alexyeoh@exampple.com +
Blk 30 Geylang Street 29, #06-40
+ family +
+ + Berinice Yu + 99272758 + berniceyu@example.com +
Blk 30 Lorong 3 Serangoon Gardens, #07-18
+ colleagues + friends +
+ owesMoney + friends + family + colleagues +
diff --git a/README.adoc b/README.adoc index 03eff3a4d191..05ecce57eb43 100644 --- a/README.adoc +++ b/README.adoc @@ -1,9 +1,9 @@ -= Address Book (Level 4) += Your TA ifdef::env-github,env-browser[:relfileprefix: docs/] -https://travis-ci.org/se-edu/addressbook-level4[image:https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master[Build Status]] +https://travis-ci.org/CS2103JAN2018-F09-B1/main[image:https://travis-ci.org/CS2103JAN2018-F09-B1/main.svg?branch=master[Build Status]] https://ci.appveyor.com/project/damithc/addressbook-level4[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] -https://coveralls.io/github/se-edu/addressbook-level4?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level4/badge.svg?branch=master[Coverage Status]] +https://coveralls.io/github/CS2103JAN2018-F09-B1/main?branch=master[image:https://coveralls.io/repos/github/CS2103JAN2018-F09-B1/main/badge.svg?branch=master[Coverage Status]] https://www.codacy.com/app/damith/addressbook-level4?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level4&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] https://gitter.im/se-edu/Lobby[image:https://badges.gitter.im/se-edu/Lobby.svg[Gitter chat]] @@ -15,13 +15,10 @@ ifndef::env-github[] image::images/Ui.png[width="600"] endif::[] -* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* This is a desktop "Your TA" application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is an address book cum scheduler targeted at making tracking students for NUS lecturer's easier. * It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language. * It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules. -* What's different from https://github.com/se-edu/addressbook-level3[level 3]: -** A more sophisticated GUI that includes a list panel and an in-built Browser. -** More test cases, including automated GUI testing. -** Support for _Build Automation_ using Gradle and for _Continuous Integration_ using Travis CI. == Site Map @@ -33,6 +30,7 @@ endif::[] == Acknowledgements +* This application was adapted from https://github.com/nus-cs2103-AY1718S2/addressbook-level4[AddressBook Level-4] * Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by _Marco Jakob_. * Libraries used: https://github.com/TomasMikula/EasyBind[EasyBind], https://github.com/TestFX/TestFX[TextFX], https://bitbucket.org/controlsfx/controlsfx/[ControlsFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/google/guava[Guava], https://github.com/junit-team/junit4[JUnit4] diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 0f0a8e7ab51e..d75ac2380077 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -3,53 +3,42 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 4 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. + -_{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ + -{empty} + +Your TA was developed by the https://github.com/CS2103JAN2018-F09-B1[F09-B1] team. + + We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. == Project Team -=== John Doe -image::damithc.jpg[width="150", align="left"] -{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>] - -Role: Project Advisor - -''' - -=== John Roe -image::lejolly.jpg[width="150", align="left"] -{empty}[http://github.com/lejolly[github]] [<>] +=== Wu Di +image::wudi.jpg[width="150", align="left"] +{empty}[https://github.com/WoodySIN[github]] -Role: Team Lead + -Responsibilities: UI +Role: Developer + +Responsibilities: Logic ''' - -=== Johnny Doe -image::yijinl.jpg[width="150", align="left"] -{empty}[http://github.com/yijinl[github]] [<>] - +=== Daniel Tan +image::joonkai1995.png[width="150", align="left"] +{empty}[http://github.com/JoonKai1995[github]] Role: Developer + -Responsibilities: Data +Responsibilities: UI ''' -=== Johnny Roe -image::m133225.jpg[width="150", align="left"] -{empty}[http://github.com/m133225[github]] [<>] +=== Pearlissa Taim +image::pearlissa.png[width="150", align="left"] +{empty}[http://github.com/Pearlissa[github]] Role: Developer + -Responsibilities: Dev Ops + Threading +Responsibilities: Model ''' -=== Benson Meier -image::yl_coder.jpg[width="150", align="left"] -{empty}[http://github.com/yl-coder[github]] [<>] +=== Ellery Chia +image::ellery.jpg[width="150", align="left"] +{empty}[http://github.com/Alaru[github]] Role: Developer + -Responsibilities: UI +Responsibilities: Storage ''' diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 1733af113b29..2bfa9b58e827 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - Developer Guide += Your TA - Developer Guide :toc: :toc-title: :toc-placement: preamble @@ -10,9 +10,9 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4/tree/master +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main/tree/master -By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +By: `F09-B1`      Since: `Jun 2016`      Licence: `MIT` == Setting up @@ -169,6 +169,7 @@ The `UI` component, * Executes user commands using the `Logic` component. * Binds itself to some data in the `Model` so that the UI can auto-update when data in the `Model` change. * Responds to events raised from various parts of the App and updates the UI accordingly. +* Default tags have background colours to identify them as of v1.2. [[Design-Logic]] === Logic component @@ -196,6 +197,7 @@ image::DeletePersonSdForLogic.png[width="800"] [[Design-Model]] === Model component +(needs new image here that includes MatriculationNumber in person) .Structure of the Model Component image::ModelClassDiagram.png[width="800"] @@ -203,10 +205,15 @@ image::ModelClassDiagram.png[width="800"] The `Model`, -* stores a `UserPref` object that represents the user's preferences. -* stores the Address Book data. -* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -* does not depend on any of the other three components. +* Stores a `UserPref` object that represents the user's preferences. +* Stores the Address Book data. +* Exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. +* Does not depend on any of the other three components. + +The `Person` Class, + +* Stores the information of a specific person(student) in the AddressBook +* Information includes: Name, Matriculation Number, Phone Number, Email, Address and different tags to associate with that person. [[Design-Storage]] === Storage component @@ -230,6 +237,13 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa This section describes some noteworthy details on how certain features are implemented. +=== Help feature +==== Current Implementation + +The help command displays a list of all the possible commands the user can make, followed by an example on its use. + +[This section is to be expanded when the help command is reworked into the help window.] + // tag::undoredo[] === Undo/Redo feature ==== Current Implementation @@ -780,15 +794,87 @@ See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step- [appendix] == Product Scope -*Target user profile*: +*Target user profile*: Tech-Savvy University Teachers/Tutors -* has a need to manage a significant number of contacts +* have the need to manage a significant number of contacts * prefer desktop apps over other types * can type fast -* prefers typing over mouse input -* is reasonably comfortable using CLI apps +* prefer typing over mouse input +* are reasonably comfortable using CLI apps + +*Value proposition*: manage contacts faster than a typical mouse/GUI driven app, includes to-do + list features (with prioritization, etc.) and scheduling (with calendar and reminders) + +=== Feature contribution + +*Wu Di* + +* *Major*: Implement the todo list + +** Support adding, editing and deleting of tasks +** Works with undo/redo functions + +This enables the tutor to view all tasks in one glance so that he/she is able to stay organized and productive. + +* *Minor*: Import feature to migrate data from an external file + +** Imports data anywhere in any OS + +This helps the tutor work on different devices with the unique data set. + +* *Minor*: add the alias feature to some of the commands + +** Support majority of commands + +This helps the tutor remember the commands intuitively and type them more efficiently. + +*Daniel* + +* *Major*: Calendar and Scheduler for user + +** Supports adding of new tasks that will be slotted into the calendar(if it has a deadline) +** Also assigns a priority value to each task based on parameters keyed in when task is added + +This helps the tutor to keep track of what needs to be done and which task to focus on. + +* *Minor*: Person has new parameter - Matriculation number + +** Person now stores matriculation number of the person +** Add command supports adding person with matriculation number(compulsory parameter) +** Find command supports search by matriculation number + +This helps the tutor to easily search for a certain student by their unique matriculation number instead of just +their names (e.g. easier than searching for a common name such as Daniel). + +*Pearlissa* + +* *Major*: Login feature + +** Implements new User package +** [Not confirmed] Encryption of data files containing usernames and passwords + +This allows multiple tutors to store their data in separate accounts, which can only be accessed by them. -*Value proposition*: manage contacts faster than a typical mouse/GUI driven app +* *Minor*: Sorting of contacts based on selected parameters + +** Any number of parameters (at least 1), and in order of priority + +This allows tutors to be better able to go through their lists of students. + +*Ellery* + +* *Major*: Display picture for all students entered + +** Support adding, editing and deleting of picture +** Also works with the redo/undo function + +This helps the tutor keep track of his students, and be able to easily remember them better. + +* *Minor*: Email feature to email students + +** Email multiple students quickly + +This helps the tutor to quickly bring up an email client to send an email to a student. [appendix] == User Stories @@ -800,15 +886,41 @@ Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (un |Priority |As a ... |I want to ... |So that I can... |`* * *` |new user |see usage instructions |refer to instructions when I forget how to use the App -|`* * *` |user |add a new person | +|`* * *` |new user |get error messages/prompts |better adapt to commands to use them properly + +|`* * *` |user |add a new person |better manage all my contacts at one go |`* * *` |user |delete a person |remove entries that I no longer need |`* * *` |user |find a person by name |locate details of persons without having to go through the entire list +|`* * *` |user |find a person by matriculation number/email |identify people easily + +|`* * *` |user |sort contacts based on name/address/email/tags |work with specific groups of people + +|`* * *` |user |assign a to-do list to each person in address book |know what I need to do for them + +|`* * *` |user |add individual items to the to-do lists |update additional tasks + +|`* * *` |user |remove entire to-do lists or items in it |remove completed tasks + +|`* * *` |user |add events to the schedule |better manage work/students + +|`* * *` |user |add a deadline to tasks/items |know what needs to be done and by when + +|`* * *` |user |prioritize tasks/items |efficiently get tasks/items done on time + |`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident -|`*` |user with many persons in the address book |sort persons by name |locate a person easily +|`* *` |user |import students/people from a text file |it is easier to enter large numbers of people + +|`* *` |user |add profile pictures |know who the people I am working with are + +|`* *` |user |mass email students/people based on a tag |easily email/inform a class of students of announcements + +|`* *` |user |set reminders for certain events |have an email sent to me before the actual event so that I don't forget + +|`*` |user with many persons in the address book |combine groups/tags |better work with people who have similar interests/work |======================================================================= _{More to be added}_ @@ -819,14 +931,14 @@ _{More to be added}_ (For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise) [discrete] -=== Use case: Delete person +=== Use case: Delete student *MSS* -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. User requests to list students +2. AddressBook shows a list of students +3. User requests to delete a specific student in the list +4. AddressBook deletes the student and all related entries (if any) + Use case ends. @@ -844,6 +956,84 @@ Use case ends. + Use case resumes at step 2. +[discrete] +=== Use case: Find a student by name + +*MSS* + +1. User requests to find a student by name +2. AddressBook shows a list of students that match the search query ++ +Use case ends. + +*Extensions* + +[none] +* 2a. The list is empty. ++ +Use case ends. + +[discrete] +=== Use case: Add event to schedule + +*MSS* + +1. User requests to add an event to a day +2. AddressBook shows the current schedule for the day +3. User requests to add the event to a timeslot for that day +4. AddressBook confirms the addition to the timeslot ++ +Use case ends. + +*Extensions* + +[none] +* 2a. The schedule for the day is full. ++ +[none] +** 2a1. AddressBook will display an error message. ++ +Use case ends. +* 3a. User tries to add it to a non-empty timeslot +[none] +** 3a1. AddressBook will display an error message. ++ +Use case resumes at step 2. + +[discrete] +=== Use case: Edit lesson for a student + +*MSS* + +1. User requests to edit lesson for a student. +2. AddressBook shows the current lessons for a student in a list. +3. User enters the index of lesson to edit. +4. AddressBook prompts the user to enter the new entry. +5. User inputs the new entry. +6. AddressBook confirms with user on the edit. +7. User confirms. +8. AddressBook replaces the old entry with the new entry. ++ +Use case ends. + +*Extensions* + +[none] +* 2a. There are no lessons for the student. ++ +Use case ends. +* 3a. User enters an invalid index +[none] +** 3a1. AddressBook will display an error message. ++ +Use case resumes at step 3. + +* 5a. User does not enter a valid lesson entry +[none] +** 5a1. AddressBook will display an error message. ++ +User case resumes at step 5. + _{More to be added}_ [appendix] @@ -852,6 +1042,11 @@ _{More to be added}_ . Should work on any <> as long as it has Java `1.8.0_60` or higher installed. . Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. . A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. +. Should be intuitive or easily understood after reading the User Guide. +. Should not exceed the size of 100 MB. +. Should respond to any requests within 3 seconds. +. Should not modify and copy any user's personal data on the computer. +. A User's data should be password protected. _{More to be added}_ @@ -864,6 +1059,43 @@ Windows, Linux, Unix, OS-X [[private-contact-detail]] Private contact detail:: A contact detail that is not meant to be shared with others +[[ui]] User interface:: +The visible interface that the user will be seeing when using the application + +[[logic]] Logic:: +The set of commands that can be executed by the application + +[[model]] Model:: +The internal memory used when application is running + +[[storage]] Storage:: +The set of instructions to store specific states and data of the application when application is not running so that it +can be loaded back into the application when application is started again. + +[[feature]] Feature:: +A specific function of the program + +[[parser]] Parser:: +A converting function or class that takes in raw input and separates it into its usable components for other methods + +[[tasks]] Tasks:: +A command to be executed + +[[deadline]] Deadline:: +The date for which certain tasks are due to be done + +[[tags]] Tags:: +Keywords tied to categories og people + +[[to-do-list]]To-do list:: +A list of things to do + +[[import]] Import:: +Bring into the application from an external source + +User - +
Developer - + [appendix] == Product Survey diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 74248917e438..eb8bb6d5cac8 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 4 - User Guide += Your TA - User Guide :toc: :toc-title: :toc-placement: preamble @@ -11,9 +11,9 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level4 +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main -By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` +By: `F09-B1` Since: `Jun 2016` Licence: `MIT` == Introduction @@ -34,7 +34,7 @@ This app will not work with earlier versions of Java 8. image::Ui.png[width="790"] + . Type the command in the command box and press kbd:[Enter] to execute it. + -e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +e.g. typing *`help`* and pressing kbd:[Enter] will list all possible commands and their formats. . Some example commands you can try: * *`list`* : lists all contacts @@ -50,6 +50,7 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. ==== *Command Format* +* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe' * Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. * 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`. * Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. @@ -58,30 +59,37 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. === Viewing help : `help` +Alias: `?` + Format: `help` === Adding a person: `add` Adds a person to the address book + -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +Alias: `a` and `+` + +Format: `add n/NAME m/MATRICULATION NUMBER p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` [TIP] A person can have any number of tags (including 0) +[NOTE] +The tags "lecturer", "TA" "student" and "T1" will appear red, yellow, blue and green respectively. + Examples: -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` +* `add n/John Doe m/A0111111X p/98765432 e/johnd@example.com a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend m/A1234567C e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` === Listing all persons : `list` Shows a list of all persons in the address book. + +Alias: `ls` + Format: `list` === Editing a person : `edit` Edits an existing person in the address book. + -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +Alias: `e` + +Format: `edit INDEX [n/NAME] [m/MATRICULATION NUMBER] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` **** * Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... @@ -98,15 +106,40 @@ Edits the phone number and email address of the 1st person to be `91234567` and * `edit 2 n/Betsy Crower t/` + Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +=== Emailing a person : `email` + +Email a person in the address book. This uses your default mail app to email. + +Format: `email INDEX` + +**** +* Emails the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* 1, 2, 3, ... +**** + +Examples: + +* `list` + +`email 2` + +Emails the 2nd person in the address book. +* `find Betsy` + +`email 1` + +Emails the 1st person in the results of the `find` command. + === Locating persons by name: `find` +=== Locating persons by name or by matriculation number: `find` + Finds persons whose names contain any of the given keywords. + +Or, finds a person whose matriculation number corresponds to the given keyword. + + +Alias: `f` + Format: `find KEYWORD [MORE_KEYWORDS]` **** * The search is case insensitive. e.g `hans` will match `Hans` * The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* Only the name is searched. +* Only the name and the matriculation number is searched. * Only full words will be matched e.g. `Han` will not match `Hans` * Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` **** @@ -114,13 +147,16 @@ Format: `find KEYWORD [MORE_KEYWORDS]` Examples: * `find John` + -Returns `john` and `John Doe` +Returns `john` and `John Doe`. * `find Betsy Tim John` + -Returns any person having names `Betsy`, `Tim`, or `John` +Returns any person having names `Betsy`, `Tim`, or `John`. +* `find A0123456X` + +Returns any person having the matriculation number A0123456X. === Deleting a person : `delete` Deletes the specified person from the address book. + +Alias: `d` and `-` + Format: `delete INDEX` **** @@ -141,6 +177,7 @@ Deletes the 1st person in the results of the `find` command. === Selecting a person : `select` Selects the person identified by the index number used in the last person listing. + +Alias: `s` + Format: `select INDEX` **** @@ -161,6 +198,7 @@ Selects the 1st person in the results of the `find` command. === Listing entered commands : `history` Lists all the commands that you have entered in reverse chronological order. + +Alias: `h` + Format: `history` [NOTE] @@ -172,6 +210,7 @@ Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and === Undoing previous command : `undo` Restores the address book to the state before the previous _undoable_ command was executed. + +Alias: `u` + Format: `undo` [NOTE] @@ -198,6 +237,7 @@ The `undo` command fails as there are no undoable commands executed previously. === Redoing the previously undone command : `redo` Reverses the most recent `undo` command. + +Alias: `r` + Format: `redo` Examples: @@ -221,8 +261,25 @@ The `redo` command fails as there are no `undo` commands executed previously. === Clearing all entries : `clear` Clears all entries from the address book. + +Alias: `c` + Format: `clear` +=== Importing data from another file : `import` + +Extracting data from an xml formatted file and +replaces the current stored data. + +Format: `import FILEPATH` + +Examples: + +* `import ~/download/NewData.xml` + +=== Sorting all entries : `sort` `[coming in v2.0]` + +Sorts all entries from the address book in alphebatical order based on name. + +Alias: `s` + +Format: `sort` + === Exiting the program : `exit` Exits the program. + diff --git a/docs/UserGuide_BACKUP_9900.adoc b/docs/UserGuide_BACKUP_9900.adoc new file mode 100644 index 000000000000..710d4ab3607e --- /dev/null +++ b/docs/UserGuide_BACKUP_9900.adoc @@ -0,0 +1,292 @@ += Your TA - User Guide +:toc: +:toc-title: +:toc-placement: preamble +:sectnums: +:imagesDir: images +:stylesDir: stylesheets +:xrefstyle: full +:experimental: +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +endif::[] +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main + +By: `F09-B1` Since: `Jun 2016` Licence: `MIT` + +== Introduction + +AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! + +== Quick Start + +. Ensure you have Java version `1.8.0_60` or later installed in your Computer. ++ +[NOTE] +Having any Java 8 version is not enough. + +This app will not work with earlier versions of Java 8. ++ +. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Address Book. +. Double-click the file to start the app. The GUI should appear in a few seconds. ++ +image::Ui.png[width="790"] ++ +. Type the command in the command box and press kbd:[Enter] to execute it. + +e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +. Some example commands you can try: + +* *`list`* : lists all contacts +* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. +* **`delete`**`3` : deletes the 3rd contact shown in the current list +* *`exit`* : exits the app + +. Refer to <> for details of each command. + +[[Features]] +== Features + +==== +*Command Format* + +* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe' +* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +* 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`. +* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +==== + +=== Viewing help : `help` + +Alias: `?` + +Format: `help` + +=== Adding a person: `add` + +Adds a person to the address book + +Alias: `a` and `+` + +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +[TIP] +A person can have any number of tags (including 0) + +Examples: + +* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` + +=== Listing all persons : `list` + +Shows a list of all persons in the address book. + +Alias: `ls` + +Format: `list` + +=== Editing a person : `edit` + +Edits an existing person in the address book. + +Alias: `e` + +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + +**** +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... +* At least one of the optional fields must be provided. +* Existing values will be updated to the input values. +* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. +* You can remove all the person's tags by typing `t/` without specifying any tags after it. +**** + +Examples: + +* `edit 1 p/91234567 e/johndoe@example.com` + +Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. +* `edit 2 n/Betsy Crower t/` + +Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. + +=== Locating persons by name: `find` + +Finds persons whose names contain any of the given keywords. + +Alias: `f` + +Format: `find KEYWORD [MORE_KEYWORDS]` + +**** +* The search is case insensitive. e.g `hans` will match `Hans` +* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` +* Only the name is searched. +* Only full words will be matched e.g. `Han` will not match `Hans` +* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +**** + +Examples: + +* `find John` + +Returns `john` and `John Doe` +* `find Betsy Tim John` + +Returns any person having names `Betsy`, `Tim`, or `John` + +=== Deleting a person : `delete` + +Deletes the specified person from the address book. + +Alias: `d` and `-` + +Format: `delete INDEX` + +**** +* Deletes the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* 1, 2, 3, ... +**** + +Examples: + +* `list` + +`delete 2` + +Deletes the 2nd person in the address book. +* `find Betsy` + +`delete 1` + +Deletes the 1st person in the results of the `find` command. + +=== Selecting a person : `select` + +Selects the person identified by the index number used in the last person listing. + +Alias: `s` + +Format: `select INDEX` + +**** +* Selects the person and loads the Google search page the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* `1, 2, 3, ...` +**** + +Examples: + +* `list` + +`select 2` + +Selects the 2nd person in the address book. +* `find Betsy` + +`select 1` + +Selects the 1st person in the results of the `find` command. + +=== Listing entered commands : `history` + +Lists all the commands that you have entered in reverse chronological order. + +Alias: `h` + +Format: `history` + +[NOTE] +==== +Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box. +==== + +// tag::undoredo[] +=== Undoing previous command : `undo` + +Restores the address book to the state before the previous _undoable_ command was executed. + +Alias: `u` + +Format: `undo` + +[NOTE] +==== +Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). +==== + +Examples: + +* `delete 1` + +`list` + +`undo` (reverses the `delete 1` command) + + +* `select 1` + +`list` + +`undo` + +The `undo` command fails as there are no undoable commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + + +=== Redoing the previously undone command : `redo` + +Reverses the most recent `undo` command. + +Alias: `r` + +Format: `redo` + +Examples: + +* `delete 1` + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + + +* `delete 1` + +`redo` + +The `redo` command fails as there are no `undo` commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + +`redo` (reapplies the `clear` command) + +// end::undoredo[] + +=== Clearing all entries : `clear` + +Clears all entries from the address book. + +Alias: `c` + +Format: `clear` + +=== Importing data from another file : `import` + +Extracting data from an xml formatted file and +replaces the current stored data. + +Format: `import FILEPATH` + +Examples: + +* `import ~/download/NewData.xml` + +=== Sorting all entries : `sort` `[coming in v2.0]` + +Sorts all entries from the address book in alphebatical order based on name. + +Alias: `s` + +Format: `sort` + +=== Exiting the program : `exit` + +Exits the program. + +Format: `exit` + +=== Saving the data + +Address book data are saved in the hard disk automatically after any command that changes the data. + +There is no need to save manually. + +// tag::dataencryption[] +=== Encrypting data files `[coming in v2.0]` + +_{explain how the user can enable/disable data encryption}_ +// end::dataencryption[] + +== FAQ + +*Q*: How do I transfer my data to another Computer? + +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. + +== Command Summary + +* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` +* *Clear* : `clear` +* *Delete* : `delete INDEX` + +e.g. `delete 3` +* *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` +* *List* : `list` +* *Help* : `help` +* *Select* : `select INDEX` + +e.g.`select 2` +* *History* : `history` +* *Undo* : `undo` +* *Redo* : `redo` diff --git a/docs/UserGuide_BASE_9900.adoc b/docs/UserGuide_BASE_9900.adoc new file mode 100644 index 000000000000..0b497b2880b2 --- /dev/null +++ b/docs/UserGuide_BASE_9900.adoc @@ -0,0 +1,276 @@ += Your TA - User Guide +:toc: +:toc-title: +:toc-placement: preamble +:sectnums: +:imagesDir: images +:stylesDir: stylesheets +:xrefstyle: full +:experimental: +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +endif::[] +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main + +By: `F09-B1` Since: `Jun 2016` Licence: `MIT` + +== Introduction + +AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! + +== Quick Start + +. Ensure you have Java version `1.8.0_60` or later installed in your Computer. ++ +[NOTE] +Having any Java 8 version is not enough. + +This app will not work with earlier versions of Java 8. ++ +. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Address Book. +. Double-click the file to start the app. The GUI should appear in a few seconds. ++ +image::Ui.png[width="790"] ++ +. Type the command in the command box and press kbd:[Enter] to execute it. + +e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +. Some example commands you can try: + +* *`list`* : lists all contacts +* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. +* **`delete`**`3` : deletes the 3rd contact shown in the current list +* *`exit`* : exits the app + +. Refer to <> for details of each command. + +[[Features]] +== Features + +==== +*Command Format* + +* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe' +* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +* 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`. +* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +==== + +=== Viewing help : `help` + +Alias: `?` + +Format: `help` + +=== Adding a person: `add` + +Adds a person to the address book + +Alias: `a` and `+` + +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +[TIP] +A person can have any number of tags (including 0) + +Examples: + +* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` + +=== Listing all persons : `list` + +Shows a list of all persons in the address book. + +Alias: `ls` + +Format: `list` + +=== Editing a person : `edit` + +Edits an existing person in the address book. + +Alias: `e` + +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + +**** +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... +* At least one of the optional fields must be provided. +* Existing values will be updated to the input values. +* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. +* You can remove all the person's tags by typing `t/` without specifying any tags after it. +**** + +Examples: + +* `edit 1 p/91234567 e/johndoe@example.com` + +Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. +* `edit 2 n/Betsy Crower t/` + +Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. + +=== Locating persons by name: `find` + +Finds persons whose names contain any of the given keywords. + +Alias: `f` + +Format: `find KEYWORD [MORE_KEYWORDS]` + +**** +* The search is case insensitive. e.g `hans` will match `Hans` +* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` +* Only the name is searched. +* Only full words will be matched e.g. `Han` will not match `Hans` +* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +**** + +Examples: + +* `find John` + +Returns `john` and `John Doe` +* `find Betsy Tim John` + +Returns any person having names `Betsy`, `Tim`, or `John` + +=== Deleting a person : `delete` + +Deletes the specified person from the address book. + +Alias: `d` and `-` + +Format: `delete INDEX` + +**** +* Deletes the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* 1, 2, 3, ... +**** + +Examples: + +* `list` + +`delete 2` + +Deletes the 2nd person in the address book. +* `find Betsy` + +`delete 1` + +Deletes the 1st person in the results of the `find` command. + +=== Selecting a person : `select` + +Selects the person identified by the index number used in the last person listing. + +Alias: `s` + +Format: `select INDEX` + +**** +* Selects the person and loads the Google search page the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* `1, 2, 3, ...` +**** + +Examples: + +* `list` + +`select 2` + +Selects the 2nd person in the address book. +* `find Betsy` + +`select 1` + +Selects the 1st person in the results of the `find` command. + +=== Listing entered commands : `history` + +Lists all the commands that you have entered in reverse chronological order. + +Alias: `h` + +Format: `history` + +[NOTE] +==== +Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box. +==== + +// tag::undoredo[] +=== Undoing previous command : `undo` + +Restores the address book to the state before the previous _undoable_ command was executed. + +Alias: `u` + +Format: `undo` + +[NOTE] +==== +Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). +==== + +Examples: + +* `delete 1` + +`list` + +`undo` (reverses the `delete 1` command) + + +* `select 1` + +`list` + +`undo` + +The `undo` command fails as there are no undoable commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + + +=== Redoing the previously undone command : `redo` + +Reverses the most recent `undo` command. + +Alias: `r` + +Format: `redo` + +Examples: + +* `delete 1` + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + + +* `delete 1` + +`redo` + +The `redo` command fails as there are no `undo` commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + +`redo` (reapplies the `clear` command) + +// end::undoredo[] + +=== Clearing all entries : `clear` + +Clears all entries from the address book. + +Alias: `c` + +Format: `clear` + +=== Exiting the program : `exit` + +Exits the program. + +Format: `exit` + +=== Saving the data + +Address book data are saved in the hard disk automatically after any command that changes the data. + +There is no need to save manually. + +// tag::dataencryption[] +=== Encrypting data files `[coming in v2.0]` + +_{explain how the user can enable/disable data encryption}_ +// end::dataencryption[] + +== FAQ + +*Q*: How do I transfer my data to another Computer? + +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. + +== Command Summary + +* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` +* *Clear* : `clear` +* *Delete* : `delete INDEX` + +e.g. `delete 3` +* *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` +* *List* : `list` +* *Help* : `help` +* *Select* : `select INDEX` + +e.g.`select 2` +* *History* : `history` +* *Undo* : `undo` +* *Redo* : `redo` diff --git a/docs/UserGuide_LOCAL_9900.adoc b/docs/UserGuide_LOCAL_9900.adoc new file mode 100644 index 000000000000..710d4ab3607e --- /dev/null +++ b/docs/UserGuide_LOCAL_9900.adoc @@ -0,0 +1,292 @@ += Your TA - User Guide +:toc: +:toc-title: +:toc-placement: preamble +:sectnums: +:imagesDir: images +:stylesDir: stylesheets +:xrefstyle: full +:experimental: +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +endif::[] +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main + +By: `F09-B1` Since: `Jun 2016` Licence: `MIT` + +== Introduction + +AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! + +== Quick Start + +. Ensure you have Java version `1.8.0_60` or later installed in your Computer. ++ +[NOTE] +Having any Java 8 version is not enough. + +This app will not work with earlier versions of Java 8. ++ +. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Address Book. +. Double-click the file to start the app. The GUI should appear in a few seconds. ++ +image::Ui.png[width="790"] ++ +. Type the command in the command box and press kbd:[Enter] to execute it. + +e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +. Some example commands you can try: + +* *`list`* : lists all contacts +* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. +* **`delete`**`3` : deletes the 3rd contact shown in the current list +* *`exit`* : exits the app + +. Refer to <> for details of each command. + +[[Features]] +== Features + +==== +*Command Format* + +* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe' +* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +* 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`. +* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +==== + +=== Viewing help : `help` + +Alias: `?` + +Format: `help` + +=== Adding a person: `add` + +Adds a person to the address book + +Alias: `a` and `+` + +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +[TIP] +A person can have any number of tags (including 0) + +Examples: + +* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` + +=== Listing all persons : `list` + +Shows a list of all persons in the address book. + +Alias: `ls` + +Format: `list` + +=== Editing a person : `edit` + +Edits an existing person in the address book. + +Alias: `e` + +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + +**** +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... +* At least one of the optional fields must be provided. +* Existing values will be updated to the input values. +* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. +* You can remove all the person's tags by typing `t/` without specifying any tags after it. +**** + +Examples: + +* `edit 1 p/91234567 e/johndoe@example.com` + +Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. +* `edit 2 n/Betsy Crower t/` + +Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. + +=== Locating persons by name: `find` + +Finds persons whose names contain any of the given keywords. + +Alias: `f` + +Format: `find KEYWORD [MORE_KEYWORDS]` + +**** +* The search is case insensitive. e.g `hans` will match `Hans` +* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` +* Only the name is searched. +* Only full words will be matched e.g. `Han` will not match `Hans` +* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +**** + +Examples: + +* `find John` + +Returns `john` and `John Doe` +* `find Betsy Tim John` + +Returns any person having names `Betsy`, `Tim`, or `John` + +=== Deleting a person : `delete` + +Deletes the specified person from the address book. + +Alias: `d` and `-` + +Format: `delete INDEX` + +**** +* Deletes the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* 1, 2, 3, ... +**** + +Examples: + +* `list` + +`delete 2` + +Deletes the 2nd person in the address book. +* `find Betsy` + +`delete 1` + +Deletes the 1st person in the results of the `find` command. + +=== Selecting a person : `select` + +Selects the person identified by the index number used in the last person listing. + +Alias: `s` + +Format: `select INDEX` + +**** +* Selects the person and loads the Google search page the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* `1, 2, 3, ...` +**** + +Examples: + +* `list` + +`select 2` + +Selects the 2nd person in the address book. +* `find Betsy` + +`select 1` + +Selects the 1st person in the results of the `find` command. + +=== Listing entered commands : `history` + +Lists all the commands that you have entered in reverse chronological order. + +Alias: `h` + +Format: `history` + +[NOTE] +==== +Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box. +==== + +// tag::undoredo[] +=== Undoing previous command : `undo` + +Restores the address book to the state before the previous _undoable_ command was executed. + +Alias: `u` + +Format: `undo` + +[NOTE] +==== +Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). +==== + +Examples: + +* `delete 1` + +`list` + +`undo` (reverses the `delete 1` command) + + +* `select 1` + +`list` + +`undo` + +The `undo` command fails as there are no undoable commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + + +=== Redoing the previously undone command : `redo` + +Reverses the most recent `undo` command. + +Alias: `r` + +Format: `redo` + +Examples: + +* `delete 1` + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + + +* `delete 1` + +`redo` + +The `redo` command fails as there are no `undo` commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + +`redo` (reapplies the `clear` command) + +// end::undoredo[] + +=== Clearing all entries : `clear` + +Clears all entries from the address book. + +Alias: `c` + +Format: `clear` + +=== Importing data from another file : `import` + +Extracting data from an xml formatted file and +replaces the current stored data. + +Format: `import FILEPATH` + +Examples: + +* `import ~/download/NewData.xml` + +=== Sorting all entries : `sort` `[coming in v2.0]` + +Sorts all entries from the address book in alphebatical order based on name. + +Alias: `s` + +Format: `sort` + +=== Exiting the program : `exit` + +Exits the program. + +Format: `exit` + +=== Saving the data + +Address book data are saved in the hard disk automatically after any command that changes the data. + +There is no need to save manually. + +// tag::dataencryption[] +=== Encrypting data files `[coming in v2.0]` + +_{explain how the user can enable/disable data encryption}_ +// end::dataencryption[] + +== FAQ + +*Q*: How do I transfer my data to another Computer? + +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. + +== Command Summary + +* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` +* *Clear* : `clear` +* *Delete* : `delete INDEX` + +e.g. `delete 3` +* *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` +* *List* : `list` +* *Help* : `help` +* *Select* : `select INDEX` + +e.g.`select 2` +* *History* : `history` +* *Undo* : `undo` +* *Redo* : `redo` diff --git a/docs/UserGuide_REMOTE_9900.adoc b/docs/UserGuide_REMOTE_9900.adoc new file mode 100644 index 000000000000..330c23eabd67 --- /dev/null +++ b/docs/UserGuide_REMOTE_9900.adoc @@ -0,0 +1,282 @@ += Your TA - User Guide +:toc: +:toc-title: +:toc-placement: preamble +:sectnums: +:imagesDir: images +:stylesDir: stylesheets +:xrefstyle: full +:experimental: +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +endif::[] +:repoURL: https://github.com/CS2103JAN2018-F09-B1/main + +By: `F09-B1` Since: `Jun 2016` Licence: `MIT` + +== Introduction + +AddressBook Level 4 (AB4) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB4 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB4 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! + +== Quick Start + +. Ensure you have Java version `1.8.0_60` or later installed in your Computer. ++ +[NOTE] +Having any Java 8 version is not enough. + +This app will not work with earlier versions of Java 8. ++ +. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your Address Book. +. Double-click the file to start the app. The GUI should appear in a few seconds. ++ +image::Ui.png[width="790"] ++ +. Type the command in the command box and press kbd:[Enter] to execute it. + +e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +. Some example commands you can try: + +* *`list`* : lists all contacts +* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. +* **`delete`**`3` : deletes the 3rd contact shown in the current list +* *`exit`* : exits the app + +. Refer to <> for details of each command. + +[[Features]] +== Features + +==== +*Command Format* + +* There are some equivalent shortcut commands known as alias with fewer alphabetic letters or a sign e.g. to add a person to the addressbook, you can type 'add n/John Doe', 'a n/John Doe' or '+ n/John Doe' +* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +* 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`. +* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +==== + +=== Viewing help : `help` + +Alias: `?` + +Format: `help` + +=== Adding a person: `add` + +Adds a person to the address book + +Alias: `a` and `+` + +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +[TIP] +A person can have any number of tags (including 0) + +Examples: + +* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` +* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` + +=== Listing all persons : `list` + +Shows a list of all persons in the address book. + +Alias: `ls` + +Format: `list` + +=== Editing a person : `edit` + +Edits an existing person in the address book. + +Alias: `e` + +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + +**** +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the last person listing. The index *must be a positive integer* 1, 2, 3, ... +* At least one of the optional fields must be provided. +* Existing values will be updated to the input values. +* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. +* You can remove all the person's tags by typing `t/` without specifying any tags after it. +**** + +Examples: + +* `edit 1 p/91234567 e/johndoe@example.com` + +Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. +* `edit 2 n/Betsy Crower t/` + +Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. + +=== Locating persons by name: `find` + +Finds persons whose names contain any of the given keywords. + +Alias: `f` + +Format: `find KEYWORD [MORE_KEYWORDS]` + +**** +* The search is case insensitive. e.g `hans` will match `Hans` +* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` +* Only the name is searched. +* Only full words will be matched e.g. `Han` will not match `Hans` +* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +**** + +Examples: + +* `find John` + +Returns `john` and `John Doe` +* `find Betsy Tim John` + +Returns any person having names `Betsy`, `Tim`, or `John` + +=== Deleting a person : `delete` + +Deletes the specified person from the address book. + +Alias: `d` and `-` + +Format: `delete INDEX` + +**** +* Deletes the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* 1, 2, 3, ... +**** + +Examples: + +* `list` + +`delete 2` + +Deletes the 2nd person in the address book. +* `find Betsy` + +`delete 1` + +Deletes the 1st person in the results of the `find` command. + +=== Selecting a person : `select` + +Selects the person identified by the index number used in the last person listing. + +Alias: `s` + +Format: `select INDEX` + +**** +* Selects the person and loads the Google search page the person at the specified `INDEX`. +* The index refers to the index number shown in the most recent listing. +* The index *must be a positive integer* `1, 2, 3, ...` +**** + +Examples: + +* `list` + +`select 2` + +Selects the 2nd person in the address book. +* `find Betsy` + +`select 1` + +Selects the 1st person in the results of the `find` command. + +=== Listing entered commands : `history` + +Lists all the commands that you have entered in reverse chronological order. + +Alias: `h` + +Format: `history` + +[NOTE] +==== +Pressing the kbd:[↑] and kbd:[↓] arrows will display the previous and next input respectively in the command box. +==== + +// tag::undoredo[] +=== Undoing previous command : `undo` + +Restores the address book to the state before the previous _undoable_ command was executed. + +Alias: `u` + +Format: `undo` + +[NOTE] +==== +Undoable commands: those commands that modify the address book's content (`add`, `delete`, `edit` and `clear`). +==== + +Examples: + +* `delete 1` + +`list` + +`undo` (reverses the `delete 1` command) + + +* `select 1` + +`list` + +`undo` + +The `undo` command fails as there are no undoable commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + + +=== Redoing the previously undone command : `redo` + +Reverses the most recent `undo` command. + +Alias: `r` + +Format: `redo` + +Examples: + +* `delete 1` + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + + +* `delete 1` + +`redo` + +The `redo` command fails as there are no `undo` commands executed previously. + +* `delete 1` + +`clear` + +`undo` (reverses the `clear` command) + +`undo` (reverses the `delete 1` command) + +`redo` (reapplies the `delete 1` command) + +`redo` (reapplies the `clear` command) + +// end::undoredo[] + +=== Clearing all entries : `clear` + +Clears all entries from the address book. + +Alias: `c` + +Format: `clear` + +=== Sorting all entries : `sort` `[coming in v2.0]` + +Sorts all entries from the address book in alphebatical order based on name. + +Alias: `s` + +Format: `sort` + +=== Exiting the program : `exit` + +Exits the program. + +Format: `exit` + +=== Saving the data + +Address book data are saved in the hard disk automatically after any command that changes the data. + +There is no need to save manually. + +// tag::dataencryption[] +=== Encrypting data files `[coming in v2.0]` + +_{explain how the user can enable/disable data encryption}_ +// end::dataencryption[] + +== FAQ + +*Q*: How do I transfer my data to another Computer? + +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. + +== Command Summary + +* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + +e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` +* *Clear* : `clear` +* *Delete* : `delete INDEX` + +e.g. `delete 3` +* *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` +* *List* : `list` +* *Help* : `help` +* *Select* : `select INDEX` + +e.g.`select 2` +* *History* : `history` +* *Undo* : `undo` +* *Redo* : `redo` diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5ec9c527b49c..87a54079d6c9 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/ellery.jpg b/docs/images/ellery.jpg new file mode 100644 index 000000000000..e56268c6ee0b Binary files /dev/null and b/docs/images/ellery.jpg differ diff --git a/docs/images/joonkai1995.png b/docs/images/joonkai1995.png new file mode 100644 index 000000000000..86f0e0570c76 Binary files /dev/null and b/docs/images/joonkai1995.png differ diff --git a/docs/images/pearlissa.png b/docs/images/pearlissa.png new file mode 100644 index 000000000000..d30ae556995f Binary files /dev/null and b/docs/images/pearlissa.png differ diff --git a/docs/images/wudi.jpg b/docs/images/wudi.jpg new file mode 100644 index 000000000000..042ce7672a82 Binary files /dev/null and b/docs/images/wudi.jpg differ diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e4695..5aefa9b91221 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -9,5 +9,7 @@ public class Messages { 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_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; + public static final String MAIL_APP_ERROR = "Error opening the default mail app on this system"; + public static final String UNSUPPORTED_DESKTOP = "The client does not support desktop operations on this system"; } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index c334710c0ea3..4d613f1d24a9 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -17,16 +18,20 @@ public class AddCommand extends UndoableCommand { public static final String COMMAND_WORD = "add"; + public static final String COMMAND_ALIAS = "a"; + public static final String COMMAND_SIGN = "+"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + "Parameters: " + PREFIX_NAME + "NAME " + + PREFIX_MATRIC_NUMBER + "MATRIC_NUMBER " + PREFIX_PHONE + "PHONE " + PREFIX_EMAIL + "EMAIL " + PREFIX_ADDRESS + "ADDRESS " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "John Doe " + + PREFIX_MATRIC_NUMBER + "A1234567J" + PREFIX_PHONE + "98765432 " + PREFIX_EMAIL + "johnd@example.com " + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index ceeb7ba913c6..6d04efaf3295 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -10,6 +10,7 @@ public class ClearCommand extends UndoableCommand { public static final String COMMAND_WORD = "clear"; + public static final String COMMAND_ALIAS = "c"; public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index b539d240001a..cb66589a0934 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -17,6 +17,8 @@ public class DeleteCommand extends UndoableCommand { public static final String COMMAND_WORD = "delete"; + public static final String COMMAND_ALIAS = "d"; + public static final String COMMAND_SIGN = "-"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes the person identified by the index number used in the last person listing.\n" diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index e6c3a3e034bc..9f2af99da340 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -21,6 +22,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.MatriculationNumber; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; @@ -34,12 +36,14 @@ public class EditCommand extends UndoableCommand { public static final String COMMAND_WORD = "edit"; + public static final String COMMAND_ALIAS = "e"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified " + "by the index number used in the last person listing. " + "Existing values will be overwritten by the input values.\n" + "Parameters: INDEX (must be a positive integer) " + "[" + PREFIX_NAME + "NAME] " + + "[" + PREFIX_MATRIC_NUMBER + "MATRICULATION NUMBER] " + "[" + PREFIX_PHONE + "PHONE] " + "[" + PREFIX_EMAIL + "EMAIL] " + "[" + PREFIX_ADDRESS + "ADDRESS] " @@ -103,12 +107,14 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript assert personToEdit != null; Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); + MatriculationNumber updatedMatricNumber = + editPersonDescriptor.getMatricNumber().orElse(personToEdit.getMatricNumber()); Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Person(updatedName, updatedMatricNumber, updatedPhone, updatedEmail, updatedAddress, updatedTags); } @Override @@ -136,6 +142,7 @@ public boolean equals(Object other) { */ public static class EditPersonDescriptor { private Name name; + private MatriculationNumber matricNumber; private Phone phone; private Email email; private Address address; @@ -149,6 +156,7 @@ public EditPersonDescriptor() {} */ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setName(toCopy.name); + setMatricNumber(toCopy.matricNumber); setPhone(toCopy.phone); setEmail(toCopy.email); setAddress(toCopy.address); @@ -159,7 +167,8 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(this.name, this.phone, this.email, this.address, this.tags); + return CollectionUtil.isAnyNonNull(this.name, this.matricNumber, this.phone, this.email, + this.address, this.tags); } public void setName(Name name) { @@ -170,6 +179,14 @@ public Optional getName() { return Optional.ofNullable(name); } + public void setMatricNumber(MatriculationNumber matricNumber) { + this.matricNumber = matricNumber; + } + + public Optional getMatricNumber() { + return Optional.ofNullable(matricNumber); + } + public void setPhone(Phone phone) { this.phone = phone; } @@ -227,6 +244,7 @@ public boolean equals(Object other) { EditPersonDescriptor e = (EditPersonDescriptor) other; return getName().equals(e.getName()) + && getMatricNumber().equals(e.getMatricNumber()) && getPhone().equals(e.getPhone()) && getEmail().equals(e.getEmail()) && getAddress().equals(e.getAddress()) diff --git a/src/main/java/seedu/address/logic/commands/EmailCommand.java b/src/main/java/seedu/address/logic/commands/EmailCommand.java new file mode 100644 index 000000000000..6247c8a17853 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/EmailCommand.java @@ -0,0 +1,68 @@ +package seedu.address.logic.commands; + +import java.awt.Desktop; +import java.awt.HeadlessException; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.commands.exceptions.UnsupportDesktopException; +import seedu.address.model.person.Person; + +/** + * Emails a person identified using it's last displayed index from the address book. + */ +public class EmailCommand extends Command { + + public static final String COMMAND_WORD = "email"; + public static final String MAIL_SYNTAX = "mailto:"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Email the person identified by the index number used in the last person listing.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + public static final String MESSAGE_EMAIL_PERSON_SUCCESS = "Email Person: %1$s"; + + private final Index targetIndex; + + public EmailCommand(Index targetIndex) { + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute() throws CommandException { + List lastShownList = model.getFilteredPersonList(); + + if (targetIndex.getZeroBased() >= lastShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + Person personToEmail = lastShownList.get(targetIndex.getZeroBased()); + + String emailAddress = personToEmail.getEmail().toString(); + String emailName = personToEmail.getName().toString(); + + try { + Desktop.getDesktop().mail(new URI(MAIL_SYNTAX + emailAddress)); + } catch (HeadlessException hlError) { + throw new UnsupportDesktopException(Messages.UNSUPPORTED_DESKTOP); + } catch (URISyntaxException Urierror) { + throw new CommandException(Messages.MAIL_APP_ERROR); + } catch (IOException e) { + throw new CommandException(Messages.MAIL_APP_ERROR); + } + + return new CommandResult(String.format(MESSAGE_EMAIL_PERSON_SUCCESS, emailName)); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof EmailCommand // instanceof handles nulls + && this.targetIndex.equals(((EmailCommand) other).targetIndex)); // state check + } +} diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index b1e671f633d2..21668568cddb 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -1,25 +1,25 @@ package seedu.address.logic.commands; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.InfoContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. - * Keyword matching is case sensitive. + * Keyword matching is not case sensitive. */ public class FindCommand extends Command { public static final String COMMAND_WORD = "find"; + public static final String COMMAND_ALIAS = "f"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " - + "the specified keywords (case-sensitive) and displays them as a list with index numbers.\n" + + "the specified keywords (not case-sensitive) and displays them as a list with index numbers.\n" + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" + "Example: " + COMMAND_WORD + " alice bob charlie"; - private final NameContainsKeywordsPredicate predicate; + private final InfoContainsKeywordsPredicate predicate; - public FindCommand(NameContainsKeywordsPredicate predicate) { - this.predicate = predicate; - } + public FindCommand(InfoContainsKeywordsPredicate predicate) { + this.predicate = predicate; } @Override public CommandResult execute() { diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index 10febf6d9136..fa2f5603cd91 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -9,6 +9,7 @@ public class HelpCommand extends Command { public static final String COMMAND_WORD = "help"; + public static final String COMMAND_SIGN = "?"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions.\n" + "Example: " + COMMAND_WORD; diff --git a/src/main/java/seedu/address/logic/commands/HistoryCommand.java b/src/main/java/seedu/address/logic/commands/HistoryCommand.java index f87abee5511d..a3a8f11563d0 100644 --- a/src/main/java/seedu/address/logic/commands/HistoryCommand.java +++ b/src/main/java/seedu/address/logic/commands/HistoryCommand.java @@ -15,6 +15,7 @@ public class HistoryCommand extends Command { public static final String COMMAND_WORD = "history"; + public static final String COMMAND_ALIAS = "h"; public static final String MESSAGE_SUCCESS = "Entered commands (from most recent to earliest):\n%1$s"; public static final String MESSAGE_NO_HISTORY = "You have not yet entered any commands."; diff --git a/src/main/java/seedu/address/logic/commands/ImportCommand.java b/src/main/java/seedu/address/logic/commands/ImportCommand.java new file mode 100644 index 000000000000..ad04b68c3f77 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/ImportCommand.java @@ -0,0 +1,48 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.io.File; +import java.io.IOException; + +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.storage.XmlFileStorage; + +/** + * Imports data from a xml file and overwrites the current data stored + */ +public class ImportCommand extends Command { + + public static final String COMMAND_WORD = "import"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Imports data from an external xml data file with " + + "the provided path and overwrites the current data stored.\n" + + "Parameters: FILE_PATH\n" + + "Example: " + COMMAND_WORD + " ~/DOWNLOADS/NewDataSet.xml"; + + public static final String MESSAGE_SUCCESS = "Data imported successfully"; + public static final String MESSAGE_INVALID_PATH = "File not found"; + public static final String MESSAGE_INVALID_FILE = "Data configuration failed"; + + private final String filePath; + + public ImportCommand(String filePath) { + this.filePath = filePath.trim(); + } + + @Override + public CommandResult execute() throws CommandException { + requireNonNull(model); + try { + ReadOnlyAddressBook newDataSet = XmlFileStorage.loadDataFromSaveFile(new File(filePath)); + model.resetData(newDataSet); + return new CommandResult(MESSAGE_SUCCESS); + } catch (IOException e) { + throw new CommandException(MESSAGE_INVALID_PATH); + } catch (DataConversionException e) { + throw new CommandException(MESSAGE_INVALID_FILE); + } + } +} diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 7b6463780824..440f944d3a07 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -8,6 +8,7 @@ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; + public static final String COMMAND_ALIAS = "ls"; public static final String MESSAGE_SUCCESS = "Listed all persons"; diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/seedu/address/logic/commands/RedoCommand.java index 7b99d0f372fc..311c95c1a1f2 100644 --- a/src/main/java/seedu/address/logic/commands/RedoCommand.java +++ b/src/main/java/seedu/address/logic/commands/RedoCommand.java @@ -13,6 +13,7 @@ public class RedoCommand extends Command { public static final String COMMAND_WORD = "redo"; + public static final String COMMAND_ALIAS = "r"; public static final String MESSAGE_SUCCESS = "Redo success!"; public static final String MESSAGE_FAILURE = "No more commands to redo!"; diff --git a/src/main/java/seedu/address/logic/commands/SelectCommand.java b/src/main/java/seedu/address/logic/commands/SelectCommand.java index 9e3840a9dde6..0bc2e3e21485 100644 --- a/src/main/java/seedu/address/logic/commands/SelectCommand.java +++ b/src/main/java/seedu/address/logic/commands/SelectCommand.java @@ -15,6 +15,7 @@ public class SelectCommand extends Command { public static final String COMMAND_WORD = "select"; + public static final String COMMAND_ALIAS = "s"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Selects the person identified by the index number used in the last person listing.\n" diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/seedu/address/logic/commands/UndoCommand.java index 1f3dcea8bbaa..7d62dcc53d38 100644 --- a/src/main/java/seedu/address/logic/commands/UndoCommand.java +++ b/src/main/java/seedu/address/logic/commands/UndoCommand.java @@ -13,6 +13,7 @@ public class UndoCommand extends Command { public static final String COMMAND_WORD = "undo"; + public static final String COMMAND_ALIAS = "u"; public static final String MESSAGE_SUCCESS = "Undo success!"; public static final String MESSAGE_FAILURE = "No more commands to undo!"; diff --git a/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java b/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java new file mode 100644 index 000000000000..c520473016fa --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/exceptions/UnsupportDesktopException.java @@ -0,0 +1,10 @@ +package seedu.address.logic.commands.exceptions; + +/** + * Represents an error which occurs during execution of a Desktop operation. + */ +public class UnsupportDesktopException extends CommandException { + public UnsupportDesktopException(String message) { + super(message); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3c729b388554..7e08c1fd0ee4 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -3,6 +3,7 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -15,6 +16,7 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.MatriculationNumber; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; @@ -32,21 +34,25 @@ public class AddCommandParser implements Parser { */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, + PREFIX_MATRIC_NUMBER, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, + PREFIX_MATRIC_NUMBER, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } try { Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).get(); + MatriculationNumber matricNumber = + ParserUtil.parseMatricNumber(argMultimap.getValue(PREFIX_MATRIC_NUMBER)).get(); Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).get(); Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).get(); Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).get(); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, address, tagList); + Person person = new Person(name, matricNumber, phone, email, address, tagList); return new AddCommand(person); } catch (IllegalValueException ive) { diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index b7d57f5db86a..81ba16731345 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -11,10 +11,12 @@ import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.EditCommand; +import seedu.address.logic.commands.EmailCommand; import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.HistoryCommand; +import seedu.address.logic.commands.ImportCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.RedoCommand; import seedu.address.logic.commands.SelectCommand; @@ -49,41 +51,60 @@ public Command parseCommand(String userInput) throws ParseException { switch (commandWord) { case AddCommand.COMMAND_WORD: + case AddCommand.COMMAND_ALIAS: + case AddCommand.COMMAND_SIGN: return new AddCommandParser().parse(arguments); case EditCommand.COMMAND_WORD: + case EditCommand.COMMAND_ALIAS: return new EditCommandParser().parse(arguments); case SelectCommand.COMMAND_WORD: + case SelectCommand.COMMAND_ALIAS: return new SelectCommandParser().parse(arguments); case DeleteCommand.COMMAND_WORD: + case DeleteCommand.COMMAND_ALIAS: + case DeleteCommand.COMMAND_SIGN: return new DeleteCommandParser().parse(arguments); + case EmailCommand.COMMAND_WORD: + return new EmailCommandParser().parse(arguments); + case ClearCommand.COMMAND_WORD: + case ClearCommand.COMMAND_ALIAS: return new ClearCommand(); case FindCommand.COMMAND_WORD: + case FindCommand.COMMAND_ALIAS: return new FindCommandParser().parse(arguments); case ListCommand.COMMAND_WORD: + case ListCommand.COMMAND_ALIAS: return new ListCommand(); case HistoryCommand.COMMAND_WORD: + case HistoryCommand.COMMAND_ALIAS: return new HistoryCommand(); case ExitCommand.COMMAND_WORD: return new ExitCommand(); case HelpCommand.COMMAND_WORD: + case HelpCommand.COMMAND_SIGN: return new HelpCommand(); case UndoCommand.COMMAND_WORD: + case UndoCommand.COMMAND_ALIAS: return new UndoCommand(); case RedoCommand.COMMAND_WORD: + case RedoCommand.COMMAND_ALIAS: return new RedoCommand(); + case ImportCommand.COMMAND_WORD: + return new ImportCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 75b1a9bf1190..7a598f83c1f7 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -7,6 +7,7 @@ public class CliSyntax { /* Prefix definitions */ public static final Prefix PREFIX_NAME = new Prefix("n/"); + public static final Prefix PREFIX_MATRIC_NUMBER = new Prefix("m/"); public static final Prefix PREFIX_PHONE = new Prefix("p/"); public static final Prefix PREFIX_EMAIL = new Prefix("e/"); public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java index c9cdbed26cf1..4ba65c45908b 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/EditCommandParser.java @@ -4,6 +4,7 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MATRIC_NUMBER; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; @@ -33,7 +34,8 @@ public class EditCommandParser implements Parser { public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_MATRIC_NUMBER, PREFIX_PHONE, + PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); Index index; @@ -46,6 +48,8 @@ public EditCommand parse(String args) throws ParseException { EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); try { ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME)).ifPresent(editPersonDescriptor::setName); + ParserUtil.parseMatricNumber(argMultimap.getValue(PREFIX_MATRIC_NUMBER)) + .ifPresent(editPersonDescriptor::setMatricNumber); ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE)).ifPresent(editPersonDescriptor::setPhone); ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL)).ifPresent(editPersonDescriptor::setEmail); ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS)).ifPresent(editPersonDescriptor::setAddress); diff --git a/src/main/java/seedu/address/logic/parser/EmailCommandParser.java b/src/main/java/seedu/address/logic/parser/EmailCommandParser.java new file mode 100644 index 000000000000..892e88f94465 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/EmailCommandParser.java @@ -0,0 +1,30 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.EmailCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new DeleteCommand object + */ +public class EmailCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the EmailCommand + * and returns an EmailCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public EmailCommand parse(String args) throws ParseException { + try { + Index index = ParserUtil.parseIndex(args); + return new EmailCommand(index); + } catch (IllegalValueException ive) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, EmailCommand.MESSAGE_USAGE)); + } + } + +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index b186a967cb94..b5f3d0c50324 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -6,7 +6,7 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.InfoContainsKeywordsPredicate; /** * Parses input arguments and creates a new FindCommand object @@ -27,7 +27,7 @@ public FindCommand parse(String args) throws ParseException { String[] nameKeywords = trimmedArgs.split("\\s+"); - return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords))); + return new FindCommand(new InfoContainsKeywordsPredicate(Arrays.asList(nameKeywords))); } } diff --git a/src/main/java/seedu/address/logic/parser/ImportCommandParser.java b/src/main/java/seedu/address/logic/parser/ImportCommandParser.java new file mode 100644 index 000000000000..5e4e37167c59 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/ImportCommandParser.java @@ -0,0 +1,28 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.logic.commands.ImportCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new ImportCommandParser object + */ +public class ImportCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the ImportCommand + * and returns an Import Command object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public ImportCommand parse(String userInput) throws ParseException { + String trimmedInput = userInput.trim(); + + String exceptionMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, ImportCommand.MESSAGE_USAGE); + if (trimmedInput.isEmpty()) { + throw new ParseException(exceptionMessage); + } + + return new ImportCommand(userInput); + } +} diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 5d6d4ae3f7b1..6f9be47c0482 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -12,6 +12,7 @@ import seedu.address.commons.util.StringUtil; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.MatriculationNumber; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; @@ -67,6 +68,32 @@ public static Optional parseName(Optional name) throws IllegalValu return name.isPresent() ? Optional.of(parseName(name.get())) : Optional.empty(); } + /** + * Parses a {@code String matricNumber} into a {@code MatriculationNumber}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws IllegalValueException if the given {@code matricNumber} is invalid. + */ + public static MatriculationNumber parseMatricNumber(String matricNumber) throws IllegalValueException { + requireNonNull(matricNumber); + String trimmedMatricNumber = matricNumber.trim(); + if (!MatriculationNumber.isValidMatricNumber(trimmedMatricNumber)) { + throw new IllegalValueException(MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS); + } + return new MatriculationNumber(trimmedMatricNumber); + } + + /** + * Parses a {@code Optional matricNumber} into an {@code Optional} + * if {@code matricNumber} is present. + * See header comment of this class regarding the use of {@code Optional} parameters. + */ + public static Optional + parseMatricNumber(Optional matricNumber) throws IllegalValueException { + requireNonNull(matricNumber); + return matricNumber.isPresent() ? Optional.of(parseMatricNumber(matricNumber.get())) : Optional.empty(); + } + /** * Parses a {@code String phone} into a {@code Phone}. * Leading and trailing whitespaces will be trimmed. diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index f8d0260de159..db4265087978 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -132,7 +132,8 @@ private Person syncWithMasterTagList(Person person) { final Set correctTagReferences = new HashSet<>(); personTags.forEach(tag -> correctTagReferences.add(masterTagObjects.get(tag))); return new Person( - person.getName(), person.getPhone(), person.getEmail(), person.getAddress(), correctTagReferences); + person.getName(), person.getMatricNumber(), + person.getPhone(), person.getEmail(), person.getAddress(), correctTagReferences); } /** diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 22a7d0eb3f4d..1ea29fe4f014 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -43,6 +43,7 @@ public ModelManager() { this(new AddressBook(), new UserPrefs()); } + @Override public void resetData(ReadOnlyAddressBook newData) { addressBook.resetData(newData); diff --git a/src/main/java/seedu/address/model/Todo/Description.java b/src/main/java/seedu/address/model/Todo/Description.java new file mode 100644 index 000000000000..8c5aef366c44 --- /dev/null +++ b/src/main/java/seedu/address/model/Todo/Description.java @@ -0,0 +1,56 @@ +package seedu.address.model.Todo; + +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a short description of a todo task + */ +public class Description { + + public static final String MESSAGE_DESCRIPTION_CONSTRAINTS = + "Task description can take any values, and it should not be blank"; + + /* + * The first character of the description must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String DESCRIPTION_VALIDATION_REGEX = "[^\\s].*"; + + public final String value; + + /** + * Constructs an {@code Description}. + * + * @param description A valid address. + */ + public Description(String description) { + assert description != null : MESSAGE_DESCRIPTION_CONSTRAINTS; + checkArgument(isValidDescription(description)); + this.value = description; + } + + /** + * Returns true if a given string is a valid person email. + */ + public static boolean isValidDescription(String test) { + return test.matches(DESCRIPTION_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Description // instanceof handles nulls + && this.value.equals(((Description) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java similarity index 51% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java index 827e2cc106bd..74787d1d9497 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java @@ -6,26 +6,28 @@ import seedu.address.commons.util.StringUtil; /** - * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. + * Tests that a {@code Person}'s {@code Name} and {@code MatriculationNumber} matches any of the keywords given. */ -public class NameContainsKeywordsPredicate implements Predicate { +public class InfoContainsKeywordsPredicate implements Predicate { private final List keywords; - public NameContainsKeywordsPredicate(List keywords) { + public InfoContainsKeywordsPredicate(List keywords) { this.keywords = keywords; } @Override public boolean test(Person person) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)) + || keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getMatricNumber().value, keyword)); } @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls - && this.keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check + || (other instanceof InfoContainsKeywordsPredicate // instanceof handles nulls + && this.keywords.equals(((InfoContainsKeywordsPredicate) other).keywords)); // state check } } diff --git a/src/main/java/seedu/address/model/person/MatriculationNumber.java b/src/main/java/seedu/address/model/person/MatriculationNumber.java new file mode 100644 index 000000000000..8c1ae5d41622 --- /dev/null +++ b/src/main/java/seedu/address/model/person/MatriculationNumber.java @@ -0,0 +1,63 @@ +package seedu.address.model.person; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a Person's matriculation number in the address book. + * Guarantees: immutable; is valid as declared in {@link #isValidMatricNumber(String)} + */ +public class MatriculationNumber { + + + public static final String MESSAGE_MATRIC_NUMBER_CONSTRAINTS = + "Matric numbers can only contain capital letters and numbers, and should contain 9 characters"; + public static final String MATRIC_NUMBER_VALIDATION_REGEX_FIRST = "[AU]{1}"; + public static final String MATRIC_NUMBER_VALIDATION_REGEX_SECOND = "\\d{7}"; + public static final String MATRIC_NUMBER_VALIDATION_REGEX_LAST = "[A-Z]{1}"; + public final String value; + + /** + * Constructs a {@code MatriculationNumber}. + * + * @param matricNumber A valid matriculation number. + */ + public MatriculationNumber(String matricNumber) { + requireNonNull(matricNumber); + checkArgument(isValidMatricNumber(matricNumber), MESSAGE_MATRIC_NUMBER_CONSTRAINTS); + this.value = matricNumber; + } + + /** + * Returns true if a given string is a valid person matriculation number. + */ + public static boolean isValidMatricNumber(String test) { + if (test.length() != 9) { + return false; + } + String firstCharacter = test.substring(0, 1); + String nextCharacters = test.substring(1, test.length() - 1); + String lastCharacter = test.substring(test.length() - 1, test.length()); + return firstCharacter.matches(MATRIC_NUMBER_VALIDATION_REGEX_FIRST) + && nextCharacters.matches(MATRIC_NUMBER_VALIDATION_REGEX_SECOND) + && lastCharacter.matches(MATRIC_NUMBER_VALIDATION_REGEX_LAST); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof MatriculationNumber // instanceof handles nulls + && this.value.equals(((MatriculationNumber) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index ec9f2aa5e919..860cf6d1b757 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -16,6 +16,7 @@ public class Person { private final Name name; + private final MatriculationNumber matricNumber; private final Phone phone; private final Email email; private final Address address; @@ -25,9 +26,10 @@ public class Person { /** * Every field must be present and not null. */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { + public Person(Name name, MatriculationNumber matricNum, Phone phone, Email email, Address address, Set tags) { requireAllNonNull(name, phone, email, address, tags); this.name = name; + this.matricNumber = matricNum; this.phone = phone; this.email = email; this.address = address; @@ -39,6 +41,9 @@ public Name getName() { return name; } + public MatriculationNumber getMatricNumber() { + return matricNumber; } + public Phone getPhone() { return phone; } @@ -71,6 +76,7 @@ public boolean equals(Object other) { Person otherPerson = (Person) other; return otherPerson.getName().equals(this.getName()) + && otherPerson.getMatricNumber().equals(this.getMatricNumber()) && otherPerson.getPhone().equals(this.getPhone()) && otherPerson.getEmail().equals(this.getEmail()) && otherPerson.getAddress().equals(this.getAddress()); @@ -79,13 +85,15 @@ public boolean equals(Object other) { @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, tags); + return Objects.hash(name, matricNumber, phone, email, address, tags); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getName()) + .append(" Matriculation Number: ") + .append(getMatricNumber()) .append(" Phone: ") .append(getPhone()) .append(" Email: ") diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index aea96bfb31f3..8f3498356c19 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -7,6 +7,7 @@ import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.MatriculationNumber; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; @@ -19,24 +20,30 @@ public class SampleDataUtil { public static Person[] getSamplePersons() { return new Person[] { - new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), + new Person(new Name("Alex Yeoh"), new MatriculationNumber("A1234567X"), + new Phone("87438807"), new Email("alexyeoh@example.com"), new Address("Blk 30 Geylang Street 29, #06-40"), - getTagSet("friends")), - new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), + getTagSet("1")), + new Person(new Name("Bernice Yu"), new MatriculationNumber("A2234567Y"), + new Phone("99272758"), new Email("berniceyu@example.com"), new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), - getTagSet("colleagues", "friends")), - new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), + getTagSet("2")), + new Person(new Name("Charlotte Oliveiro"), new MatriculationNumber("A1234567X"), + new Phone("93210283"), new Email("charlotte@example.com"), new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), - getTagSet("neighbours")), - new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), + getTagSet("exchange")), + new Person(new Name("David Li"), new MatriculationNumber("A3234567J"), + new Phone("91031282"), new Email("lidavid@example.com"), new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), - getTagSet("family")), - new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), + getTagSet("retaking")), + new Person(new Name("Irfan Ibrahim"), new MatriculationNumber("A4234567K"), + new Phone("92492021"), new Email("irfan@example.com"), new Address("Blk 47 Tampines Street 20, #17-35"), - getTagSet("classmates")), - new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), + getTagSet("friend")), + new Person(new Name("Roy Balakrishnan"), new MatriculationNumber("A5234567G"), + new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), - getTagSet("colleagues")) + getTagSet("brother")) }; } diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java index cf5b527c063a..cba76a48324f 100644 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ b/src/main/java/seedu/address/storage/AddressBookStorage.java @@ -41,4 +41,10 @@ public interface AddressBookStorage { */ void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) throws IOException; + /** + * Saves the given (@link ReadOnlyAddressBook) to storage as a backup + * @param addressBook cannot be null + * @throws IOException if there is any issue writing to the temporary file + */ + void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException; } diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index 53967b391a5a..f7a29e8e2170 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -77,6 +77,10 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) th addressBookStorage.saveAddressBook(addressBook, filePath); } + @Override + public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException { + backupAddressBook(addressBook); + } @Override @Subscribe diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java index 2cd92dc4fd20..a25d0d31a2c5 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java @@ -11,6 +11,7 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.person.Address; import seedu.address.model.person.Email; +import seedu.address.model.person.MatriculationNumber; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; @@ -26,6 +27,8 @@ public class XmlAdaptedPerson { @XmlElement(required = true) private String name; @XmlElement(required = true) + private String matricNumber; + @XmlElement(required = true) private String phone; @XmlElement(required = true) private String email; @@ -44,8 +47,10 @@ public XmlAdaptedPerson() {} /** * Constructs an {@code XmlAdaptedPerson} with the given person details. */ - public XmlAdaptedPerson(String name, String phone, String email, String address, List tagged) { + public XmlAdaptedPerson(String name, String matricNumber, String phone, + String email, String address, List tagged) { this.name = name; + this.matricNumber = matricNumber; this.phone = phone; this.email = email; this.address = address; @@ -61,6 +66,7 @@ public XmlAdaptedPerson(String name, String phone, String email, String address, */ public XmlAdaptedPerson(Person source) { name = source.getName().fullName; + matricNumber = source.getMatricNumber().value; phone = source.getPhone().value; email = source.getEmail().value; address = source.getAddress().value; @@ -89,6 +95,17 @@ public Person toModelType() throws IllegalValueException { } final Name name = new Name(this.name); + if (this.matricNumber == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + MatriculationNumber.class.getSimpleName())); + } + + if (!MatriculationNumber.isValidMatricNumber(this.matricNumber)) { + throw new IllegalValueException(MatriculationNumber.MESSAGE_MATRIC_NUMBER_CONSTRAINTS); + } + + final MatriculationNumber matricNumber = new MatriculationNumber(this.matricNumber); + if (this.phone == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName())); } @@ -114,7 +131,7 @@ public Person toModelType() throws IllegalValueException { final Address address = new Address(this.address); final Set tags = new HashSet<>(personTags); - return new Person(name, phone, email, address, tags); + return new Person(name, matricNumber, phone, email, address, tags); } @Override @@ -129,6 +146,7 @@ public boolean equals(Object other) { XmlAdaptedPerson otherPerson = (XmlAdaptedPerson) other; return Objects.equals(name, otherPerson.name) + && Objects.equals(matricNumber, otherPerson.matricNumber) && Objects.equals(phone, otherPerson.phone) && Objects.equals(email, otherPerson.email) && Objects.equals(address, otherPerson.address) diff --git a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java b/src/main/java/seedu/address/storage/XmlAddressBookStorage.java index c77ebe67435c..79ca2b80202d 100644 --- a/src/main/java/seedu/address/storage/XmlAddressBookStorage.java +++ b/src/main/java/seedu/address/storage/XmlAddressBookStorage.java @@ -79,4 +79,9 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) th XmlFileStorage.saveDataToFile(file, new XmlSerializableAddressBook(addressBook)); } + @Override + public void backupAddressBook(ReadOnlyAddressBook addressBook) throws IOException { + saveAddressBook(addressBook, (filePath + ".bak")); + } + } diff --git a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java index dc820896c312..2efa7eccb495 100644 --- a/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java +++ b/src/main/java/seedu/address/storage/XmlSerializableAddressBook.java @@ -7,15 +7,19 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.person.Person; +import seedu.address.model.tag.Tag; /** * An Immutable AddressBook that is serializable to XML format */ @XmlRootElement(name = "addressbook") -public class XmlSerializableAddressBook { +public class XmlSerializableAddressBook implements ReadOnlyAddressBook { @XmlElement private List persons; @@ -70,4 +74,28 @@ public boolean equals(Object other) { XmlSerializableAddressBook otherAb = (XmlSerializableAddressBook) other; return persons.equals(otherAb.persons) && tags.equals(otherAb.tags); } + + @Override + public ObservableList getPersonList() { + final ObservableList persons = this.persons.stream().map(p -> { + try { + return p.toModelType(); + } catch (IllegalValueException e) { + return null; + } + }).collect(Collectors.toCollection(FXCollections::observableArrayList)); + return FXCollections.unmodifiableObservableList(persons); + } + + @Override + public ObservableList getTagList() { + final ObservableList tags = this.tags.stream().map(t -> { + try { + return t.toModelType(); + } catch (IllegalValueException e) { + return null; + } + }).collect(Collectors.toCollection(FXCollections::observableArrayList)); + return FXCollections.unmodifiableObservableList(tags); + } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index f6727ea83abd..6303f1027b45 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -14,6 +14,16 @@ public class PersonCard extends UiPart { private static final String FXML = "PersonListCard.fxml"; + private static final String lecturerTag = "lecturer"; + + private static final String TATag = "TA"; + + private static final String studentTag = "student"; + + private static final String tutorial1Tag = "T1"; + + private static final String[] TAG_COLOR_STYLES = { "teal", "orange", "brown", "pink", "black", "grey" }; + /** * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. * As a consequence, UI elements' variable names cannot be set to such keywords @@ -29,6 +39,8 @@ public class PersonCard extends UiPart { @FXML private Label name; @FXML + private Label matricNumber; + @FXML private Label id; @FXML private Label phone; @@ -44,10 +56,46 @@ public PersonCard(Person person, int displayedIndex) { this.person = person; id.setText(displayedIndex + ". "); name.setText(person.getName().fullName); + matricNumber.setText(person.getMatricNumber().value); phone.setText(person.getPhone().value); address.setText(person.getAddress().value); email.setText(person.getEmail().value); - person.getTags().forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + initTags(person); + } + + /** + * Returns the color style for {@code tagName}'s label. + */ + private String getTagColorStyleFor(String tagName) { + // we use the hash code of the tag name to generate a random color, so that the color remain consistent + // between different runs of the program while still making it random enough between tags. + switch (tagName) { + case lecturerTag: + return "red"; + + case TATag: + return "yellow"; + + case studentTag: + return "blue"; + + case tutorial1Tag: + return "green"; + + default: + return TAG_COLOR_STYLES[Math.abs(tagName.hashCode()) % TAG_COLOR_STYLES.length]; + } + } + + /** + * Creates the tag labels for {@code person}. + */ + private void initTags(Person person) { + person.getTags().forEach(tag -> { + Label tagLabel = new Label(tag.tagName); + tagLabel.getStyleClass().add(getTagColorStyleFor(tag.tagName)); + tags.getChildren().add(tagLabel); + }); } @Override diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index d06336391cca..fe6df9a36a2d 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -342,10 +342,104 @@ } #tags .label { - -fx-text-fill: white; - -fx-background-color: #3e7b91; -fx-padding: 1 3 1 3; -fx-border-radius: 2; -fx-background-radius: 2; -fx-font-size: 11; } + +#tags .teal { + -fx-text-fill: white; + -fx-background-color: #3e7b91; +} + +#tags .red { + -fx-text-fill: black; + -fx-background-color: red; +} + +#tags .yellow { + -fx-background-color: yellow; + -fx-text-fill: black; +} + +#tags .blue { + -fx-text-fill: white; + -fx-background-color: blue; +} + +#tags .orange { + -fx-text-fill: black; + -fx-background-color: orange; +} + +#tags .brown { + -fx-text-fill: white; + -fx-background-color: brown; +} + +#tags .green { + -fx-text-fill: black; + -fx-background-color: green; +} + +#tags .pink { + -fx-text-fill: black; + -fx-background-color: pink; +} + +#tags .black { + -fx-text-fill: white; + -fx-background-color: black; +} + +#tags .grey { + -fx-text-fill: black; + -fx-background-color: grey; +} + +.tab-pane { + -fx-padding: 0 0 0 1; + -fx-background-color: #232A34; +} + +.tab-pane .tab-header-area { + -fx-background-color: #232A34; + -fx-padding: 0 0 0 0; + -fx-min-height: 0; + -fx-max-height: 0; +} + +.tab-pane .tab-header-area .tab-header-background { + -fx-opacity: 0; +} + +.tab-pane { + -fx-tab-min-width:150px; +} + +.tab { + -fx-background-insets: 0 1 0 1,0,0; +} + +.tab-pane .tab { + -fx-background-color: #404040; + +} + +.tab-pane .tab:selected { + -fx-border-color: transparent !important; + -fx-background-color: #5F6A6A; +} + +.tab .tab-label { + -fx-alignment: CENTER; + -fx-text-fill: #f3f3f3; + -fx-font-size: 12px; + -fx-font-weight: bold; +} + +.tab:selected .tab-label { + -fx-border-color: transparent !important; + -fx-text-fill: white; +} diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 1dadb95b6ffe..2606328e3442 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -11,6 +11,8 @@ + + @@ -47,14 +49,21 @@ - - - - - + + + + + + + + + + + - + + diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index f08ea32ad558..51a2dac3743c 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -28,6 +28,7 @@