From 4b890b5ce945ba76a526eea3f39f08b746a97cf4 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Fri, 18 Feb 2022 00:35:46 +0800 Subject: [PATCH 001/140] Dummy commit to trigger CI --- dummy.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 dummy.txt diff --git a/dummy.txt b/dummy.txt new file mode 100644 index 00000000000..b0469fe4e8b --- /dev/null +++ b/dummy.txt @@ -0,0 +1 @@ +This is for a dummy commit to trigger CI. \ No newline at end of file From 9399127b9cfec6a4129d1bec01668b811e60bf38 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Fri, 18 Feb 2022 00:37:59 +0800 Subject: [PATCH 002/140] Re: dummy commit --- dummy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dummy.txt b/dummy.txt index b0469fe4e8b..7db933aafa3 100644 --- a/dummy.txt +++ b/dummy.txt @@ -1 +1 @@ -This is for a dummy commit to trigger CI. \ No newline at end of file +This is for a dummy commit to trigger CI. From 349a04225881e54f3d2af26b6f00f18650c28a9e Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Fri, 18 Feb 2022 00:42:18 +0800 Subject: [PATCH 003/140] Update Codecov badge --- docs/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 7601dbaad0d..a47f0cc2093 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,8 +4,7 @@ title: AddressBook Level-3 --- [![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) -[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3) - +[![codecov](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp/branch/master/graph/badge.svg?token=G5ITTT4UTJ)](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp) ![Ui](images/Ui.png) **AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). From 706415653893a437e23adfab6677e7d3b994430a Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sun, 20 Feb 2022 17:37:51 +0800 Subject: [PATCH 004/140] Update AboutUs --- docs/AboutUs.md | 56 ++++++++++++++----------------------- docs/images/castryl.png | Bin 0 -> 91624 bytes docs/images/ivorcmx.png | Bin 0 -> 111490 bytes docs/images/putaojuice.png | Bin 0 -> 100028 bytes docs/images/yumengtan.png | Bin 0 -> 116400 bytes 5 files changed, 21 insertions(+), 35 deletions(-) create mode 100644 docs/images/castryl.png create mode 100644 docs/images/ivorcmx.png create mode 100644 docs/images/putaojuice.png create mode 100644 docs/images/yumengtan.png diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1c9514e966a..1d72b49dab9 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,59 +1,45 @@ --- -layout: page -title: About Us +ABOUT US --- We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg). -You can reach us at the email `seer[at]comp.nus.edu.sg` +You can reach us at the email `e0544443@u.nus.edu` ## Project team -### John Doe +### Chen Yu An - + -[[homepage](http://www.comp.nus.edu.sg/~damithch)] -[[github](https://github.com/johndoe)] -[[portfolio](team/johndoe.md)] - -* Role: Project Advisor - -### Jane Doe - - - -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/putaojuice)] +[[portfolio](team/putaojuice.md)] * Role: Team Lead -* Responsibilities: UI -### Johnny Doe +### Low Weimin, Ian - + -[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] +[[github](http://github.com/castryl] +[[portfolio](team/castryl.md)] -* Role: Developer -* Responsibilities: Data +* Role: Documentation -### Jean Doe +### Ivor Chua - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/ivorcmx)] +[[portfolio](team/ivorcmx.md)] -* Role: Developer -* Responsibilities: Dev Ops + Threading +* Role: Testing -### James Doe +### Tan Yu Meng - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/yumengtan)] +[[portfolio](team/yumengtan.md)] -* Role: Developer -* Responsibilities: UI +* Role: Code Quality diff --git a/docs/images/castryl.png b/docs/images/castryl.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd5274a824105f1de2ac8245bff52f044ebf359 GIT binary patch literal 91624 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
Rx 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

4ZW$Au-1+@TOjZrMtst~~QifNfW7@G;F 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 b1M~j_oqNdr0G7g100000NkvXXu0mjfcmz4v literal 0 HcmV?d00001 diff --git a/docs/images/yumengtan.png b/docs/images/yumengtan.png new file mode 100644 index 0000000000000000000000000000000000000000..f06209d3f0860dd593da4dbbd97e3bb2d6c4daa1 GIT binary patch literal 116400 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�ByyykqG*jV1*p#%it%^)E2(8lv)VldflovMPYA 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ޟ)Efy$4B@ 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 literal 0 HcmV?d00001 From 2805836a0fb65566594f105eaf5b22967d53d237 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sun, 20 Feb 2022 17:48:49 +0800 Subject: [PATCH 005/140] Added PPP for Ivor --- docs/team/ivorcmx.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docs/team/ivorcmx.md diff --git a/docs/team/ivorcmx.md b/docs/team/ivorcmx.md new file mode 100644 index 00000000000..ab8c8c701de --- /dev/null +++ b/docs/team/ivorcmx.md @@ -0,0 +1,33 @@ +--- +Ivor Chua's Project Portfolio Page +--- + +### Project: NUScheduler + +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. + +Given below are my contributions to the project. + +* **New Feature**: TBA +* **New Feature**: TBA + +* **Code contributed**: [RepoSense link]() TBA + +* **Project management**: + * TBA + +* **Enhancements to existing features**: + * TBA + +* **Documentation**: + * User Guide: + * TBA + * Developer Guide: + * TBA + +* **Community**: + * TBA + +* **Tools**: + * TBA + From 104f713ad96d8a137f5f9b096f27dcc8ad9992bc Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 23 Feb 2022 22:13:59 +0800 Subject: [PATCH 006/140] Add PPP --- docs/team/yumengtan.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/team/yumengtan.md diff --git a/docs/team/yumengtan.md b/docs/team/yumengtan.md new file mode 100644 index 00000000000..42c95d53455 --- /dev/null +++ b/docs/team/yumengtan.md @@ -0,0 +1,38 @@ +--- +layout: page +title: Tan Yu Meng's Project Portfolio Page +--- +### Project: NUScheduler +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. + +Given below are my contributions to the project. + +* **New Feature**: + * to be added soon + +* **New Feature**: + * to be added soon + +* **Code contributed**: [RepoSense link (to be added soon)]() + +* **Project management**: + * to be added soon + +* **Enhancements to existing features**: + * to be added soon + +* **Documentation**: + * User Guide: + * to be added soon + * Developer Guide: + * to be added soon + +* **Community**: + * to be added soon + +* **Tools**: + * to be added soon + + From fc5e328086b39da5fe2b280fba6dc0cb831b35c7 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 23 Feb 2022 22:49:13 +0800 Subject: [PATCH 007/140] Update README. Change Ui.png --- README.md | 34 +++++++++++++++++++++++----------- docs/images/Ui.png | Bin 14607 -> 26434 bytes 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 13f5c77403f..047ff018d52 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,26 @@ -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) ![Ui](docs/images/Ui.png) -* This is **a sample project for Software Engineering (SE) students**.
- Example usages: - * as a starting point of a course project (as opposed to writing everything from scratch) - * as a case study -* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details. - * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big. - * It comes with a **reasonable level of user and developer documentation**. -* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...). -* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**. -* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. +# NUScheduler +*** + +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps.
+ +## Uses: + * keep track of all school contacts, modules and tasks + * organise academic life in a neat manner + +*** + +## Features: + * Add a task/contact + * Delete a task/contact + * Update a task/contact + * Add a label to task + * View all tasks and their deadlines + * View all contacts + * Remind upcoming tasks + diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2429edac366ebe3e00650b6dd909d8..9d9dff887ead8975fafb9a043a5d4abab167d97f 100644 GIT binary patch literal 26434 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 RAXge19gVx{rMDi1{6Bg4z)AoB From df573175edcc8ed5f3ee4143dd5fe2130870e3a6 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sun, 27 Feb 2022 20:48:44 +0800 Subject: [PATCH 008/140] Update UserGuide - Update UserGuide with draft UG for v1.1 --- docs/UserGuide.md | 234 +++++++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 106 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3716f3ca8a4..ba0f0c8fe1d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,180 +2,197 @@ layout: page title: User Guide --- - -AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. - -* Table of Contents -{:toc} +#User Guide - NUScheduler +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. + +- Quick Start +- Features + - Task Management + - Add task + - Delete task + - Update task + - Add a label to a task + - View all tasks and their deadlines + - Contact Management + - Add contact + - Delete contact + - Update contact + - View all contacts + - Reminder + - Remind the user of upcoming tasks + - Exit the app +- FAQ +- CLI Summary -------------------------------------------------------------------------------------------------------------------- ## Quick start -1. Ensure you have Java `11` or above installed in your Computer. +1. Ensure you have `Java 11` or above installed in your Computer. -1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). +2. Download the latest `NUScheduler.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). -1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +3. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. -1. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
+4. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
![Ui](images/Ui.png) -1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+5. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: + 1. `view c` : Lists all contacts. + 2. `add c` /John Doe /[johnd@example.com](mailto:johnd@example.com) /johntele: Adds a contact named John Doe to the Address Book. + 3. `add tn/Assignment 1 m/CS1101s` : Adds an `assignment/task` of the specified module to NUScheduler. + 4. `del c 3` : Deletes the 3rd contact shown in the current list. + 5. `del t 3` : Deletes the 3rd task shown in the current task list. + 6. `upd t 3 n/Assignment 2 m/CS1231s` : Updates the specified task in the current list. + 7. `exit` : Exits the app. - * **`list`** : Lists all contacts. +6. Refer to the [Features](#features) below for details of each command. - * **`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. +## Features - * **`clear`** : Deletes all contacts. +
- * **`exit`** : Exits the app. +**:information_source: Notes about the command format:**
-1. Refer to the [Features](#features) below for details of each command. +**Notes about the command format:** --------------------------------------------------------------------------------------------------------------------- +- Words in **UPPER_CASE** are the parameters to be supplied by the user.e.g. in `add t n /NAME`, **NAME** is a parameter +- which can be used as `add t n /John Doe`. +- Items in **square brackets** are optional.e.g `/NAME [/TAG]` can be used as `/John Doe /friend` or as `/John Doe`. +- Parameters cannot be in any order and must follow the order given in the command format.e.g. if the command format +- specifies `add t /DESCRIPTION /DEADLINE [/TAG]`, the details must be entered as `/DESCRIPTION /DEADLINE [/TAG]`. +- All `` fields must be > 0 -## Features +
-
+### Feature - Add a task: `add t` -**:information_source: Notes about the command format:**
+Adds a task to the task list. -* 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`. +Format: `add t /DESCRIPTION /DEADLINE [/TAG]` -* 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`. +Example: `add t /Buy groceries /2022 02 22 5pm [/Important]` -* Items with `…`​ after them can be used multiple times including zero times.
- e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +### Feature - Delete a task: `del t ` -* 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. +Deletes a task from the task list, where `` is the ID of the task. -* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `p/12341234 p/56785678`, only `p/56785678` will be taken. +Format: `del t ` -* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +Example: `del t 3` -
+### Feature - Update a task description: `upd t d ` -### Viewing help : `help` +Updates a task in the task list, where `` is the ID of the task. -Shows a message explaning how to access the help page. +Format: `upd t d   /DESCRIPTION` -![help message](images/helpMessage.png) +Example: `upd t d 3 /Buy groceries` -Format: `help` +### Feature - Update a task deadline: `upd t t ` +Updates a task in the task list, where `` is the ID of the task. -### Adding a person: `add` +Format: `upd t t /DEADLINE` -Adds a person to the address book. +Example: `upd t t /2022 03 10 12pm` -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` +### Feature - Label a task: `lab t ` -
:bulb: **Tip:** -A person can have any number of tags (including 0) -
+Label a task based on a specific tag, where `` is the ID of the task. -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` +Format: `label t tag` + +Example: `label t 3 important` -### Listing all persons : `list` +### Feature - View all tasks: `view t` -Shows a list of all persons in the address book. +View all the tasks currently in the task list. -Format: `list` +Format: `view t` -### Editing a person : `edit` +### Feature - Add contact: `add c` -Edits an existing person in the address book. +Adds a person to address book. -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +Format: `add c /NAME /EMAIL /TELEGRAM [/TAG]` -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. 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. +The Telegram handle can be entered with or without an @ symbol in front. 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` +- `add c /John Doe /johnd@example.com /johndtele /Group Member` +- `add c /Betsy Crow /betsycrow@example.com /betsyc` -Finds persons whose names contain any of the given keywords. +### Feature - Delete contact: `del c ` -Format: `find KEYWORD [MORE_KEYWORDS]` +Deletes a contact from the contact list. -* 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` +Format: `del c ` -Examples: -* `find John` returns `john` and `John Doe` -* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png) +Example: `del c 3` -### Deleting a person : `delete` +### Feature - Update contact: `upd c ` -Deletes the specified person from the address book. +Updates a contact from the contact list. -Format: `delete INDEX` +Format:  `upd c /NAME /EMAIL /TELEGRAM [/TAG] ` -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index **must be a positive integer** 1, 2, 3, …​ +Update a contact’s information, where `` is the contact’s unique identifier. -Examples: -* `list` followed by `delete 2` deletes the 2nd person in the address book. -* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command. +Example: `upd c /John Doe  /johndoe@example.com /johntele 23` -### Clearing all entries : `clear` +### Feature - View all contacts: `view c` -Clears all entries from the address book. +View all the contacts currently in the contact list. -Format: `clear` +Format: `view c [to] [t] [/TAG]` -### Exiting the program : `exit` +The optional parameter `[to]` will return the contact list in tag order instead of the default alphabetical order. -Exits the program. +The optional parameter `[t]` requires a tag input and will return contacts from that tag only. -Format: `exit` +Examples: -### Saving the data +- `view c` +- `view c to` +- `view c t /Friends` -AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. +### Feature - Remind the user of upcoming tasks: `remind` -### Editing the data file +Reminds the user of all the tasks with upcoming deadlines (within 7 days by default). -AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file. +Format: `remind []` -
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. -
+The optional `[]` specifies the number of days to check tasks against and return. -### Archiving data files `[coming in v2.0]` +Tasks are returned in ascending order of time to deadline (closest deadline first). -_Details coming soon ..._ +Example: `remind 10` + +### Feature - Exit the app: `exit` + +Exits the app. + +Format: exit + +### Feature - Saving the data + +NUScheduler data is saved in the hard disk automatically after any command that changes the data. There is no manual save function. -------------------------------------------------------------------------------------------------------------------- ## 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 AddressBook home folder. +**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 NUScheduler home folder. -------------------------------------------------------------------------------------------------------------------- @@ -183,10 +200,15 @@ _Details coming soon ..._ Action | Format, Examples --------|------------------ -**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` +**add t** | `add t /DESCRIPTION /DEADLINE [/TAG]`
e.g., `add t /Buy groceries /2022 02 22 5pm /Important` +**del t ** | `del t `
e.g., `del t 3` +**upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` +**upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` +**lab t ** | `label t tag`
e.g., `label t 3 important` +**view t** | `view t` +**add c** | `add c /NAME /EMAIL /TELEGRAM [/TAG]`
e.g., `add c /Betsy Crow /betsycrow@example.com /betsyc /Group Member` +**del c ** | `del c `
e.g., `del c 3` +**upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` +**view c** | `view c [to] [t] [/TAG]`
e.g., `view c` +**remind** | `remind []`
e.g., `remind 10` +**exit** | `exit` From ef1eb3118ab5e310599530f2edde7b16c7099755 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sun, 27 Feb 2022 20:56:44 +0800 Subject: [PATCH 009/140] Add Skeletal PPP --- docs/team/putaojuice.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/team/putaojuice.md diff --git a/docs/team/putaojuice.md b/docs/team/putaojuice.md new file mode 100644 index 00000000000..42f19b2e621 --- /dev/null +++ b/docs/team/putaojuice.md @@ -0,0 +1,38 @@ +--- +layout: page +title: Chen Yu An's Project Portfolio Page +--- +### Project: NUScheduler +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. + +Given below are my contributions to the project. + +* **New Feature**: + * to be added soon + +* **New Feature**: + * to be added soon + +* **Code contributed**: [RepoSense link (to be added soon)]() + +* **Project management**: + * to be added soon + +* **Enhancements to existing features**: + * to be added soon + +* **Documentation**: + * User Guide: + * to be added soon + * Developer Guide: + * to be added soon + +* **Community**: + * to be added soon + +* **Tools**: + * to be added soon + + From ba374e2bd63fe6ca6879dbf671b45c89df21b94e Mon Sep 17 00:00:00 2001 From: yumengtan Date: Tue, 1 Mar 2022 09:29:38 +0800 Subject: [PATCH 010/140] Add acknowledgement and update _config.yml to fit project. --- README.md | 10 ++++++++-- docs/_config.yml | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 047ff018d52..de367eef77b 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,13 @@ optimized for use via a Command Line Interface (CLI) while still having the bene If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps.
## Uses: +*** * keep track of all school contacts, modules and tasks * organise academic life in a neat manner - -*** + ## Features: +*** * Add a task/contact * Delete a task/contact * Update a task/contact @@ -24,3 +25,8 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona * View all contacts * Remind upcoming tasks +## Acknowledgements +*** +This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative.](https://se-education.org) + + diff --git a/docs/_config.yml b/docs/_config.yml index 6bd245d8f4e..fac10d78b89 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,4 +1,4 @@ -title: "AB-3" +title: "NUScheduler" theme: minima header_pages: @@ -8,7 +8,7 @@ header_pages: markdown: kramdown -repository: "se-edu/addressbook-level3" +repository: "AY2122S2-CS2103-F11-4/tp" github_icon: "images/github-icon.png" plugins: From d467b55020cf867fa7e77a46407b0b07d827745f Mon Sep 17 00:00:00 2001 From: castryl Date: Tue, 8 Mar 2022 22:50:26 +0800 Subject: [PATCH 011/140] Update DG and PPP --- docs/DeveloperGuide.md | 142 +++++++++++++++++++++++++++++++++-------- docs/team/castryl.md | 38 +++++++++++ 2 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 docs/team/castryl.md diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 46eae8ee565..18ec0890081 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -257,42 +257,44 @@ _{Explain here how the data archiving feature will be implemented}_ **Target user profile**: -* has a need to manage a significant number of contacts -* prefer desktop apps over other types -* can type fast -* prefers typing to mouse interactions -* is reasonably comfortable using CLI apps +NUScheduler is for Year 1 NUS Computing students who prefer CLI over GUI and has a lot of academic tasks to keep track of. -**Value proposition**: manage contacts faster than a typical mouse/GUI driven app +**Value proposition**: This app has simple CLI and a sleek GUI that allows the user to manage the tasks easily and efficiently. It will be mainly used to keep track NUS assignments and projects across multiple modules. ### User stories Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| 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 | | -| `* * *` | 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 | hide private contact details | 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 | +| Priority | As a …​ | I want to …​ | So that I can…​ | +|----------| ------------------------------------------ | ------------------------------------ | ------------------------------------------------------------------ | +| `* * *` | beginner user | add a task | keep track of the task | +| `* * *` | beginner user | delete a task | remove a task I have completed | +| `* * *` | beginner user | edit a task | change details of a task | +| `* * *` | beginner user | view all tasks | keep track of all my current tasks | +| `* * *` | beginner user | add a contact | keep track of all my contacts | +| `* * *` | beginner user | delete a contact | delete an incorrect/unneeded contact | +| `* * *` | beginner user | edit a contact | correct/update a a contact | +| `* * *` | beginner user | view all contacts | view all my current contacts | +| `* * *` | beginner user | add a label | know which task is for which module | +| `* * *` | potential user | use simple commands | learn the commands easily | +| `* * *` | year 1 computing student | keep track of assignment deadlines | complete the tasks on time | +| `*` | beginner user | see a reminder of tasks from the app | know what are my upcoming deadlines | *{More to be added}* ### Use cases -(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise) +(For all use cases below, the **System** is the `NUScheduler` and the **Actor** is the `user`, unless specified otherwise) -**Use case: Delete a person** +**Use case: Delete a contact** **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 contacts +2. NUScheduler shows a list of contacts +3. User requests to delete a specific contact in the list +4. NUScheduler deletes the contact Use case ends. @@ -304,17 +306,105 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * 3a. The given index is invalid. - * 3a1. AddressBook shows an error message. + * 3a1. NUScheduler shows an error message. Use case resumes at step 2. -*{More to be added}* +**Use case: Add a task** + +**MSS** + +1. User requests to add a task with add task command +2. NUScheduler adds the user's defined task to the task list + + Use case ends. + +**Extensions** + +* 2a. The task description is empty. + * 2a1. NUScheduler prompts the user to fill up the description. + + Use case ends. + +* 2b. The task deadline has a wrong time format. + * 2b1. NUScheduler shows an error message. + + Use case ends. + +**Use case: Delete a task** + +**MSS** + +1. User requests to delete a task with delete task command +2. NUScheduler deletes task specified from task list + + Use case ends. + +**Extensions** + +* 2a. The task list is empty. + * 2a1. NUScheduler shows an error message. + + Use case ends. + +* 2b. The task number to delete is invalid. + * 2b1. NUScheduler shows an error message. + + Use case ends. + +**Use case: View all tasks** + +**MSS** + +1. User requests to view all the tasks with view command +2. NUScheduler shows all the tasks from task list + + Use case ends. + +**Extensions** + +* 2a. The task list is empty. + * 2a1. NUScheduler shows a message that the task list is empty. + + Use case ends. + +**Use case: Find a task** + +**MSS** + +1. User requests to find tasks with find command +2. NUScheduler shows a list of tasks from task list. + + Use case ends. + +**Extensions** + +* 2a. The task list is empty. + * 2a1. NUScheduler shows a message that the task list is empty. + + Use case ends. + +* 2b. No task matches. + * 2b1. NUScheduler shows a message that there are no tasks that matches the description. + + Use case ends. + +* 2c. Tasks found. + * 2c1. NUScheduler shows all the tasks that matches with the keyword. + + Use case ends. ### Non-Functional Requirements -1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. -2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. -3. 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. +1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. +2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. +3. 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. +4. The command used should be simple to learn. +5. The system should be usable by a novice who has never used the system before. +6. The system should be backward compatible with data produced by earlier versions of the system. +7. Each command should not take more than 2 second to complete and display the result. +8. Texts in the UI should wrap around. +9. The project is expected to adhere to a schedule that delivers a feature set every milestone. *{More to be added}* @@ -322,6 +412,8 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * **Mainstream OS**: Windows, Linux, Unix, OS-X * **Private contact detail**: A contact detail that is not meant to be shared with others +* **Task**: A task with descriptions and/or deadline +* **Task list**: A task list of all the tasks -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/team/castryl.md b/docs/team/castryl.md new file mode 100644 index 00000000000..23e563c2166 --- /dev/null +++ b/docs/team/castryl.md @@ -0,0 +1,38 @@ +--- +layout: page +title: Ian's Project Portfolio Page +--- +### Project: NUScheduler +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. + +Given below are my contributions to the project. + +* **New Feature**: + * to be added soon + +* **New Feature**: + * to be added soon + +* **Code contributed**: [RepoSense link (to be added soon)]() + +* **Project management**: + * to be added soon + +* **Enhancements to existing features**: + * to be added soon + +* **Documentation**: + * User Guide: + * to be added soon + * Developer Guide: + * to be added soon + +* **Community**: + * to be added soon + +* **Tools**: + * to be added soon + + From 9f8023ab02a61b3f43730f6cc4cf041ed55fc9aa Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:03:52 +0800 Subject: [PATCH 012/140] Add "add task" command - Add AddTaskCommand - Add AddTaskCommandParser - Add model.task.Task - Add model.TaskList - Modify Model (Interface) - Modify ModelManager - include TaskList in constructor --- .../logic/commands/AddTaskCommand.java | 77 +++++++++++++++++++ .../logic/parser/AddTaskCommandParser.java | 37 +++++++++ .../logic/parser/AddressBookParser.java | 4 + .../seedu/address/logic/parser/CliSyntax.java | 2 + src/main/java/seedu/address/model/Model.java | 5 ++ .../seedu/address/model/ModelManager.java | 16 ++++ .../java/seedu/address/model/TaskList.java | 21 +++++ .../java/seedu/address/model/task/Task.java | 16 ++++ 8 files changed, 178 insertions(+) create mode 100644 src/main/java/seedu/address/logic/commands/AddTaskCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java create mode 100644 src/main/java/seedu/address/model/TaskList.java create mode 100644 src/main/java/seedu/address/model/task/Task.java diff --git a/src/main/java/seedu/address/logic/commands/AddTaskCommand.java b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java new file mode 100644 index 00000000000..b6475c671eb --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java @@ -0,0 +1,77 @@ +package seedu.address.logic.commands; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.task.Task; + +/** + * Add a task to the system. + */ +public class AddTaskCommand extends Command { + public static final String COMMAND_WORD = "addt"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Add a task with description and/or deadline. \n" + + "Format: addt d/[DESCRIPTION] t/[DEADLINE]\n" + + "Example: " + COMMAND_WORD + " " + PREFIX_ADD_TASK_DESCRIPTION + + "Swimming lesson " + PREFIX_ADD_TASK_DEADLINE + "03/05/2022"; + + public static final String MESSAGE_ARGUMENTS = "Task added.\n" + "Description: %1$s\n" + "Deadline: %2$s"; + + public static final String MESSAGE_NO_DESCRIPTION = "Task description not found!"; + + private final String description; + private final String deadline; + + public AddTaskCommand(String description) { + requireAllNonNull(description); + + this.description = description; + this.deadline = "No deadline set"; + } + + public AddTaskCommand(String description, String deadline) { + requireAllNonNull(description, deadline); + + this.description = description; + this.deadline = deadline; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireAllNonNull(model); + + if (this.description.equals("")) { + // missing description, prompt the user with the format + throw new CommandException(MESSAGE_NO_DESCRIPTION + "\n" + MESSAGE_USAGE); + } + + model.addTask(new Task(description, deadline)); + + // Printing out the current items in task list to make sure the method work, should be removed later on + System.out.println(model.getTaskList().getTaskList().toString()); + + return new CommandResult(String.format(MESSAGE_ARGUMENTS, description, deadline)); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof AddTaskCommand)) { + return false; + } + + // state check + AddTaskCommand e = (AddTaskCommand) other; + return description.equals(e.description); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java new file mode 100644 index 00000000000..715cdfd558c --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -0,0 +1,37 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.logic.commands.AddTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new {@code AddTaskCommand} object + */ +public class AddTaskCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the {@code AddTaskCommand} + * and returns a {@code AddTaskCommand} object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public AddTaskCommand parse(String args) throws ParseException { + requireNonNull(args); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, PREFIX_ADD_TASK_DEADLINE); + + String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + + if (deadline.equals("")) { + // task without deadline set + return new AddTaskCommand(description); + } else { + // task with deadline set + return new AddTaskCommand(description, deadline); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 1e466792b46..98295154d70 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -7,6 +7,7 @@ import java.util.regex.Pattern; import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.AddTaskCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; @@ -68,6 +69,9 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD: return new HelpCommand(); + case AddTaskCommand.COMMAND_WORD: + return new AddTaskCommandParser().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 75b1a9bf119..63981444232 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -11,5 +11,7 @@ public class CliSyntax { public static final Prefix PREFIX_EMAIL = new Prefix("e/"); public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_ADD_TASK_DESCRIPTION = new Prefix("d/"); + public static final Prefix PREFIX_ADD_TASK_DEADLINE = new Prefix("t/"); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..db44afa718a 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -4,6 +4,7 @@ import java.util.function.Predicate; import javafx.collections.ObservableList; +import seedu.address.model.task.Task; import seedu.address.commons.core.GuiSettings; import seedu.address.model.person.Person; @@ -84,4 +85,8 @@ public interface Model { * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + void addTask(Task task); + + TaskList getTaskList(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 86c1df298d7..21fd74d38c1 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -9,6 +9,7 @@ import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; +import seedu.address.model.task.Task; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; import seedu.address.model.person.Person; @@ -23,6 +24,8 @@ public class ModelManager implements Model { private final UserPrefs userPrefs; private final FilteredList filteredPersons; + private final TaskList taskList; + /** * Initializes a ModelManager with the given addressBook and userPrefs. */ @@ -34,6 +37,8 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + + this.taskList = new TaskList(); } public ModelManager() { @@ -147,4 +152,15 @@ public boolean equals(Object obj) { && filteredPersons.equals(other.filteredPersons); } + //=========== TaskList ================================================================================== + + @Override + public void addTask(Task task) { + taskList.addTask(task); + } + + @Override + public TaskList getTaskList() { + return this.taskList; + } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java new file mode 100644 index 00000000000..13acbaa6912 --- /dev/null +++ b/src/main/java/seedu/address/model/TaskList.java @@ -0,0 +1,21 @@ +package seedu.address.model; + +import seedu.address.model.task.Task; + +import java.util.ArrayList; + +public class TaskList { + private final ArrayList taskList; + + public TaskList() { + this.taskList = new ArrayList<>(); + } + + public void addTask(Task task) { + this.taskList.add(task); + } + + public ArrayList getTaskList() { + return this.taskList; + } +} diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java new file mode 100644 index 00000000000..4e8ed6214cd --- /dev/null +++ b/src/main/java/seedu/address/model/task/Task.java @@ -0,0 +1,16 @@ +package seedu.address.model.task; + +public class Task { + private final String description; + private final String deadline; + + public Task(String description, String deadline) { + this.description = description; + this.deadline = deadline; + } + + @Override + public String toString() { + return "Task: " + this.description + " " + deadline; + } +} From 543b28c89afb64afbe47b6356e215335015e75c5 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:17:01 +0800 Subject: [PATCH 013/140] Check for checkstyle - Add javadoc comments - Rearrange import statements --- .../java/seedu/address/logic/commands/AddTaskCommand.java | 8 +++++++- .../seedu/address/logic/parser/AddTaskCommandParser.java | 8 +++----- src/main/java/seedu/address/model/Model.java | 2 +- src/main/java/seedu/address/model/ModelManager.java | 2 +- src/main/java/seedu/address/model/TaskList.java | 4 ++-- src/main/java/seedu/address/model/task/Task.java | 3 +++ 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/AddTaskCommand.java b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java index b6475c671eb..bb61673579f 100644 --- a/src/main/java/seedu/address/logic/commands/AddTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java @@ -1,8 +1,8 @@ package seedu.address.logic.commands; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; @@ -27,6 +27,9 @@ public class AddTaskCommand extends Command { private final String description; private final String deadline; + /** + * Initializes a AddTaskCommand with the given description. The deadline is not set. + */ public AddTaskCommand(String description) { requireAllNonNull(description); @@ -34,6 +37,9 @@ public AddTaskCommand(String description) { this.deadline = "No deadline set"; } + /** + * Initializes a AddTaskCommand with the given description and deadline. + */ public AddTaskCommand(String description, String deadline) { requireAllNonNull(description, deadline); diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index 715cdfd558c..55d6ab5e5f0 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -1,12 +1,9 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.AddTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -21,7 +18,8 @@ public class AddTaskCommandParser implements Parser { */ public AddTaskCommand parse(String args) throws ParseException { requireNonNull(args); - ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, PREFIX_ADD_TASK_DEADLINE); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, + PREFIX_ADD_TASK_DEADLINE); String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index db44afa718a..69f025fd182 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -4,9 +4,9 @@ import java.util.function.Predicate; import javafx.collections.ObservableList; -import seedu.address.model.task.Task; import seedu.address.commons.core.GuiSettings; import seedu.address.model.person.Person; +import seedu.address.model.task.Task; /** * The API of the Model component. diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 21fd74d38c1..1fb4689dbf3 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -9,10 +9,10 @@ import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; -import seedu.address.model.task.Task; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; import seedu.address.model.person.Person; +import seedu.address.model.task.Task; /** * Represents the in-memory model of the address book data. diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 13acbaa6912..ab85142bdcf 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -1,9 +1,9 @@ package seedu.address.model; -import seedu.address.model.task.Task; - import java.util.ArrayList; +import seedu.address.model.task.Task; + public class TaskList { private final ArrayList taskList; diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 4e8ed6214cd..4cb63b71688 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -4,6 +4,9 @@ public class Task { private final String description; private final String deadline; + /** + * Initializes a Task with a description and deadline. + */ public Task(String description, String deadline) { this.description = description; this.deadline = deadline; From 4ea0f231f07b903a7d49c0373d53392fe65c7f3e Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:31:34 +0800 Subject: [PATCH 014/140] Add test class to test AddTaskCommand - Add AddTaskCommandTest --- .../logic/commands/AddCommandTest.java | 12 ++ .../logic/commands/AddTaskCommandTest.java | 115 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 5865713d5dd..e5ea1231956 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -20,7 +20,9 @@ import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; import seedu.address.model.person.Person; +import seedu.address.model.task.Task; import seedu.address.testutil.PersonBuilder; public class AddCommandTest { @@ -147,6 +149,16 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public void addTask(Task task) { + throw new AssertionError("This method should not be called."); + } + + @Override + public TaskList getTaskList() { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java new file mode 100644 index 00000000000..636ff899df9 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -0,0 +1,115 @@ +package seedu.address.logic.commands; + +import static seedu.address.testutil.Assert.assertThrows; + +import java.nio.file.Path; +import java.util.function.Predicate; + +import org.junit.jupiter.api.Test; + +import javafx.collections.ObservableList; +import seedu.address.commons.core.GuiSettings; +import seedu.address.model.Model; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; +import seedu.address.model.person.Person; +import seedu.address.model.task.Task; + +public class AddTaskCommandTest { + + @Test + public void constructor_nullDescription_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new AddTaskCommand(null)); + } + + @Test + public void constructor_nullDescriptionAndDeadline_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new AddTaskCommand(null, null)); + } + + /** + * A default model stub that have all of the methods failing. + */ + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addTask(Task task) { + throw new AssertionError("This method should not be called."); + } + + @Override + public TaskList getTaskList() { + throw new AssertionError("This method should not be called."); + } + } +} From 23be4dd85758a0d93f6aa9488863bfe56cddbe3d Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 00:32:19 +0800 Subject: [PATCH 015/140] Added delete task command ("delt") to work --- .../address/commons/util/StringUtil.java | 11 +++ .../logic/commands/DeleteTaskCommand.java | 75 +++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 + .../logic/parser/DeleteTaskCommandParser.java | 30 ++++++++ .../address/logic/parser/ParserUtil.java | 15 +++- src/main/java/seedu/address/model/Model.java | 2 + .../seedu/address/model/ModelManager.java | 5 ++ .../java/seedu/address/model/TaskList.java | 8 ++ 8 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index 61cc8c9a1cb..99602b57108 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -65,4 +65,15 @@ public static boolean isNonZeroUnsignedInteger(String s) { return false; } } + + public static boolean isInvalidNumber(String s) { + requireNonNull(s); + + try { + Integer a = Integer.parseInt(s.replaceAll("[^0-9]", "")); + return true; + } catch (NumberFormatException nfe) { + return false; + } + } } diff --git a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java new file mode 100644 index 00000000000..9475048aa36 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java @@ -0,0 +1,75 @@ +package seedu.address.logic.commands; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; + +/** + * Delete a task from the system + */ +public class DeleteTaskCommand extends Command { + public static final String COMMAND_WORD = "delt"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Delete a task number from current tasklist using given index. \n" + + "Format: delt [tasknumber]. \n" + + "Example: " + COMMAND_WORD + " " + "1"; + + public static final String MESSAGE_ARGUMENTS = "Task %1$s deleted"; + + public static final String MESSAGE_NO_INDEX = "Task number not found!"; + + public static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Task number does not exist in current task list!"; + + private final Integer taskNumber; + + /** + * Initializes a DeleteTaskCommand with the given taskNumber + * @param taskNumber index to be deleted + */ + public DeleteTaskCommand(Integer taskNumber) { + requireAllNonNull(taskNumber); + this.taskNumber = taskNumber; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireAllNonNull(model); + + if (this.taskNumber.equals("")) { + // missing taskNumber, prompt the user with the format + throw new CommandException(MESSAGE_NO_INDEX + "\n" + MESSAGE_USAGE); + } else if (this.taskNumber <= 0 || this.taskNumber > model.getTaskList().size()) { + throw new CommandException(MESSAGE_INDEX_OUT_OF_BOUNDS + "\n" + MESSAGE_USAGE); + } + + model.deleteTask(taskNumber); + + // Printing out current items in list to ensure item is deleted + System.out.println(model.getTaskList().size()); + + return new CommandResult(String.format(MESSAGE_ARGUMENTS, taskNumber)); + + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof DeleteTaskCommand)) { + return false; + } + + //state check + DeleteTaskCommand e = (DeleteTaskCommand) other; + return taskNumber.equals(e.taskNumber); + } + + + +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 98295154d70..afb02ee428f 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -11,6 +11,7 @@ import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; +import seedu.address.logic.commands.DeleteTaskCommand; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; @@ -72,6 +73,9 @@ public Command parseCommand(String userInput) throws ParseException { case AddTaskCommand.COMMAND_WORD: return new AddTaskCommandParser().parse(arguments); + case DeleteTaskCommand.COMMAND_WORD: + return new DeleteTaskCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java new file mode 100644 index 00000000000..410d1013f93 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java @@ -0,0 +1,30 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import seedu.address.logic.commands.DeleteCommand; +import seedu.address.logic.commands.DeleteTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new DeleteTaskCommand object + */ +public class DeleteTaskCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the DeleteTaskCommand + * and returns a DeleteTaskCommand object for execution. + * @throws ParseException if the user input does not conform to the expected format + */ + public DeleteTaskCommand parse(String args) throws ParseException { + requireNonNull(args); + try { + Integer taskNumber = ParserUtil.parseNumber(args); + return new DeleteTaskCommand(taskNumber); + } catch (ParseException pe) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); + } + + } +} diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index b117acb9c55..9b4cee30318 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -20,7 +20,7 @@ */ public class ParserUtil { - public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; + public static final String MESSAGE_INVALID_INDEX = "Index is not valid."; /** * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be @@ -121,4 +121,17 @@ public static Set parseTags(Collection tags) throws ParseException } return tagSet; } + + public static Integer parseNumber(String oneBasedIndex) throws ParseException { + String trimmedIndex = oneBasedIndex.trim(); + if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { + throw new ParseException(MESSAGE_INVALID_INDEX); + } + + if (!StringUtil.isInvalidNumber(trimmedIndex)) { + throw new ParseException(MESSAGE_INVALID_INDEX); + } + + return Integer.parseInt(trimmedIndex.replaceAll("[^0-9]", "")); + } } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 69f025fd182..c43e25752e9 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -89,4 +89,6 @@ public interface Model { void addTask(Task task); TaskList getTaskList(); + + void deleteTask(Integer taskNumber); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 1fb4689dbf3..9d09f5ef9b7 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -163,4 +163,9 @@ public void addTask(Task task) { public TaskList getTaskList() { return this.taskList; } + + @Override + public void deleteTask(Integer taskNumber) { + taskList.deleteTask(taskNumber); + } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index ab85142bdcf..eb657c9f29a 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -18,4 +18,12 @@ public void addTask(Task task) { public ArrayList getTaskList() { return this.taskList; } + + public int size() { + return this.taskList.size(); + } + + public void deleteTask(Integer taskNumber) { + taskList.remove(taskNumber - 1); // to convert to zero-based indexing + } } From 9e03c972a2184d927ff6e6bd123e24476eac3d24 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 00:33:48 +0800 Subject: [PATCH 016/140] Updated UG to match delete task command keyword --- docs/UserGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ba0f0c8fe1d..5e799a13865 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -45,7 +45,7 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona 2. `add c` /John Doe /[johnd@example.com](mailto:johnd@example.com) /johntele: Adds a contact named John Doe to the Address Book. 3. `add tn/Assignment 1 m/CS1101s` : Adds an `assignment/task` of the specified module to NUScheduler. 4. `del c 3` : Deletes the 3rd contact shown in the current list. - 5. `del t 3` : Deletes the 3rd task shown in the current task list. + 5. `delt 3` : Deletes the 3rd task shown in the current task list. 6. `upd t 3 n/Assignment 2 m/CS1231s` : Updates the specified task in the current list. 7. `exit` : Exits the app. @@ -78,13 +78,13 @@ Format: `add t /DESCRIPTION /DEADLINE [/TAG]` Example: `add t /Buy groceries /2022 02 22 5pm [/Important]` -### Feature - Delete a task: `del t ` +### Feature - Delete a task: `delt ` Deletes a task from the task list, where `` is the ID of the task. -Format: `del t ` +Format: `delt ` -Example: `del t 3` +Example: `delt 3` ### Feature - Update a task description: `upd t d ` @@ -201,7 +201,7 @@ data of your previous NUScheduler home folder. Action | Format, Examples --------|------------------ **add t** | `add t /DESCRIPTION /DEADLINE [/TAG]`
e.g., `add t /Buy groceries /2022 02 22 5pm /Important` -**del t ** | `del t `
e.g., `del t 3` +**delt ** | `del t `
e.g., `del t 3` **upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` **upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` **lab t ** | `label t tag`
e.g., `label t 3 important` From a4906abe4b833496891728a526c5414bdacc3658 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 00:48:31 +0800 Subject: [PATCH 017/140] Added missing javadoc comments --- src/main/java/seedu/address/commons/util/StringUtil.java | 7 +++++++ .../address/logic/parser/DeleteTaskCommandParser.java | 1 + src/main/java/seedu/address/logic/parser/ParserUtil.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index 99602b57108..05a1e3dc007 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -66,6 +66,13 @@ public static boolean isNonZeroUnsignedInteger(String s) { } } + /** + * Returns true if {@code s} the index is valid number + * e.g. delt 1 + * Will return false for any other invalid inout + * e.g. empty string, delt abc + * @throws NullPointerException if {@code s} is null. + */ public static boolean isInvalidNumber(String s) { requireNonNull(s); diff --git a/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java index 410d1013f93..f177071a7ed 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DeleteTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 9b4cee30318..f3d14e8fa46 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -122,6 +122,11 @@ public static Set parseTags(Collection tags) throws ParseException return tagSet; } + /** + * Parses {@code oneBasedIndex} into an Integer and returns it. Leading and trailing whitespaces will be + * trimmed. + * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). + */ public static Integer parseNumber(String oneBasedIndex) throws ParseException { String trimmedIndex = oneBasedIndex.trim(); if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { From d07715e381cc3828cda3a9aa53c4563d7745ba97 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 15:12:29 +0800 Subject: [PATCH 018/140] Add deleteTaskCommandTest --- .../seedu/address/model/ModelManager.java | 2 + .../logic/commands/AddCommandTest.java | 5 + .../logic/commands/AddTaskCommandTest.java | 5 + .../logic/commands/DeleteTaskCommandTest.java | 111 ++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 9d09f5ef9b7..96747b91701 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -164,6 +164,8 @@ public TaskList getTaskList() { return this.taskList; } + //=========== Delete Task ================================================================================== + @Override public void deleteTask(Integer taskNumber) { taskList.deleteTask(taskNumber); diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index e5ea1231956..12a7f1ae382 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -159,6 +159,11 @@ public void addTask(Task task) { public TaskList getTaskList() { throw new AssertionError("This method should not be called."); } + + @Override + public void deleteTask(Integer taskNumber) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 636ff899df9..242d7a1c2e2 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -111,5 +111,10 @@ public void addTask(Task task) { public TaskList getTaskList() { throw new AssertionError("This method should not be called."); } + + @Override + public void deleteTask(Integer taskNumber) { + throw new AssertionError("This method should not be called"); + } } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java new file mode 100644 index 00000000000..948371329aa --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -0,0 +1,111 @@ +package seedu.address.logic.commands; + +import static seedu.address.testutil.Assert.assertThrows; +import java.nio.file.Path; +import java.util.function.Predicate; +import org.junit.jupiter.api.Test; +import javafx.collections.ObservableList; +import seedu.address.commons.core.GuiSettings; +import seedu.address.model.Model; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; +import seedu.address.model.person.Person; +import seedu.address.model.task.Task; + +public class DeleteTaskCommandTest { + @Test + public void constructor_nullDescription_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new DeleteTaskCommand(null)); + } + + /** + * A default model stub that have all of the methods failing. + */ + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addTask(Task task) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteTask(Integer taskNumber) { + throw new AssertionError("This method should not be called."); + } + + @Override + public TaskList getTaskList() { + throw new AssertionError("This method should not be called."); + } + } +} From 10cdeb10a9e0536449e661f5afe16617a8d1521f Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 15:17:24 +0800 Subject: [PATCH 019/140] Updated checkstyleTest --- .../seedu/address/logic/commands/DeleteTaskCommandTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 948371329aa..ea8e261349c 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -1,9 +1,12 @@ package seedu.address.logic.commands; import static seedu.address.testutil.Assert.assertThrows; + import java.nio.file.Path; import java.util.function.Predicate; + import org.junit.jupiter.api.Test; + import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; import seedu.address.model.Model; From 863969f80893bbf93cffbe6376aa3bfb1ec19c90 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 17:16:47 +0800 Subject: [PATCH 020/140] Updated logic of parser to detect invalid index --- .../java/seedu/address/commons/util/StringUtil.java | 12 +++++++++--- .../java/seedu/address/logic/parser/ParserUtil.java | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index 05a1e3dc007..de663c108d8 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -69,7 +69,7 @@ public static boolean isNonZeroUnsignedInteger(String s) { /** * Returns true if {@code s} the index is valid number * e.g. delt 1 - * Will return false for any other invalid inout + * Will return false for any other invalid input * e.g. empty string, delt abc * @throws NullPointerException if {@code s} is null. */ @@ -77,10 +77,16 @@ public static boolean isInvalidNumber(String s) { requireNonNull(s); try { - Integer a = Integer.parseInt(s.replaceAll("[^0-9]", "")); - return true; + String subStringWithoutPrefix = s.substring(5); + if (subStringWithoutPrefix.matches("[0-9]+")) { + return true; + } else { + throw new NumberFormatException(); + } } catch (NumberFormatException nfe) { return false; + } catch (StringIndexOutOfBoundsException e) { + return false; } } } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index f3d14e8fa46..81aa15b8b2f 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -133,10 +133,10 @@ public static Integer parseNumber(String oneBasedIndex) throws ParseException { throw new ParseException(MESSAGE_INVALID_INDEX); } - if (!StringUtil.isInvalidNumber(trimmedIndex)) { + if (StringUtil.isInvalidNumber(trimmedIndex)) { throw new ParseException(MESSAGE_INVALID_INDEX); } - return Integer.parseInt(trimmedIndex.replaceAll("[^0-9]", "")); + return Integer.parseInt(trimmedIndex); } } From b072378a6ba87047a26796bb92595f5475c0959c Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 12 Mar 2022 18:33:36 +0800 Subject: [PATCH 021/140] Updated parser to allow for whitespaces for "delt" --- .../address/commons/util/StringUtil.java | 24 ------------------- .../address/logic/parser/ParserUtil.java | 6 ++--- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index de663c108d8..61cc8c9a1cb 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -65,28 +65,4 @@ public static boolean isNonZeroUnsignedInteger(String s) { return false; } } - - /** - * Returns true if {@code s} the index is valid number - * e.g. delt 1 - * Will return false for any other invalid input - * e.g. empty string, delt abc - * @throws NullPointerException if {@code s} is null. - */ - public static boolean isInvalidNumber(String s) { - requireNonNull(s); - - try { - String subStringWithoutPrefix = s.substring(5); - if (subStringWithoutPrefix.matches("[0-9]+")) { - return true; - } else { - throw new NumberFormatException(); - } - } catch (NumberFormatException nfe) { - return false; - } catch (StringIndexOutOfBoundsException e) { - return false; - } - } } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 81aa15b8b2f..f7951875067 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -22,6 +22,8 @@ public class ParserUtil { public static final String MESSAGE_INVALID_INDEX = "Index is not valid."; + public static final String MESSAGE_INVALID_FIRSTCHAR = "Index starts with empty whitespace"; + /** * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be * trimmed. @@ -133,10 +135,6 @@ public static Integer parseNumber(String oneBasedIndex) throws ParseException { throw new ParseException(MESSAGE_INVALID_INDEX); } - if (StringUtil.isInvalidNumber(trimmedIndex)) { - throw new ParseException(MESSAGE_INVALID_INDEX); - } - return Integer.parseInt(trimmedIndex); } } From 49cc709de0a6bf87864941d588c6af5c58be6c0a Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sat, 12 Mar 2022 19:12:19 +0800 Subject: [PATCH 022/140] Bug fix add task command - Fix bug where user can enter multiple description or deadline prefixes and still able to add task --- .../logic/parser/AddTaskCommandParser.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index 55d6ab5e5f0..18ccb7f4d1b 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -1,12 +1,15 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; import seedu.address.logic.commands.AddTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; +import java.util.List; + /** * Parses input arguments and creates a new {@code AddTaskCommand} object */ @@ -21,6 +24,20 @@ public AddTaskCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, PREFIX_ADD_TASK_DEADLINE); + try { + List description = argMultimap.getAllValues(PREFIX_ADD_TASK_DESCRIPTION); + List deadline = argMultimap.getAllValues(PREFIX_ADD_TASK_DEADLINE); + + if (description.size() > 1 || deadline.size() > 1) { + // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } catch(ParseException e) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + + //TODO try-catch block for deadline input has to be formatted + String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); From 1e8745a65b1b7c39849c096e5da3d6eb70078db6 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sat, 12 Mar 2022 19:18:02 +0800 Subject: [PATCH 023/140] Rearrange import statements --- .../seedu/address/logic/parser/AddTaskCommandParser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index 18ccb7f4d1b..ab393764b60 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -5,11 +5,11 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import java.util.List; + import seedu.address.logic.commands.AddTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; -import java.util.List; - /** * Parses input arguments and creates a new {@code AddTaskCommand} object */ @@ -32,7 +32,7 @@ public AddTaskCommand parse(String args) throws ParseException { // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); } - } catch(ParseException e) { + } catch (ParseException e) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); } From 4fefa5943f7a7f1eac4caf951f45819641098b27 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Sun, 13 Mar 2022 16:32:44 +0800 Subject: [PATCH 024/140] Add "find task" command - Add FindTaskCommand - Add FindTaskCommandParser - Add FindTaskCommandTest - Modify model.TaskList - Modify model.ModelManager -Modify model.Model --- .../logic/commands/FindTaskCommand.java | 95 +++++++++++++ .../logic/parser/AddressBookParser.java | 4 + .../logic/parser/FindTaskCommandParser.java | 21 +++ src/main/java/seedu/address/model/Model.java | 7 + .../seedu/address/model/ModelManager.java | 8 ++ .../java/seedu/address/model/TaskList.java | 14 ++ .../logic/commands/AddTaskCommandTest.java | 5 + .../logic/commands/DeleteTaskCommandTest.java | 4 + .../logic/commands/FindTaskCommandTest.java | 130 ++++++++++++++++++ 9 files changed, 288 insertions(+) create mode 100644 src/main/java/seedu/address/logic/commands/FindTaskCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java create mode 100644 src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java diff --git a/src/main/java/seedu/address/logic/commands/FindTaskCommand.java b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java new file mode 100644 index 00000000000..eb642572094 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java @@ -0,0 +1,95 @@ +package seedu.address.logic.commands; + + +import static java.util.Objects.requireNonNull; + + +import java.util.ArrayList; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.task.Task; + +/** + * finds a task to the system based on user input. + */ +public class FindTaskCommand extends Command { + + public static final String COMMAND_WORD = "findt"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": finds a task based on keywords. \n" + + "Format: findt [INPUT] \n" + + "Example: " + COMMAND_WORD + " " + "Swimming lessons"; + + public static final String MESSAGE_ARGUMENTS = "Here are the matching tasks in the list:\n" + "%1$s"; + + public static final String MESSAGE_NO_DESCRIPTION = "Unable to find any matching tasks due to empty keyword"; + + public static final String MESSAGE_NO_MATCHING_TASK = "Unable to find any matching tasks based on input"; + + private final String input; + + /** + * Initializes a FindTaskCommand with the given input. + */ + public FindTaskCommand(String input){ + requireNonNull(input); + this.input = input; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + if (this.input.equals("")) { + throw new CommandException(MESSAGE_NO_DESCRIPTION + "\n" + MESSAGE_USAGE); + } + ArrayList matchingList = model.findTask(input); + String output = getOutput(matchingList); + + if (matchingList.size() == 0) { + throw new CommandException(MESSAGE_NO_MATCHING_TASK); + } + + // Ensure that tasklist is not changed, to be deleted later + System.out.println(model.findTask(input).toString()); + + return new CommandResult(String.format(MESSAGE_ARGUMENTS, output)); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof FindTaskCommand)) { + return false; + } + + //state check + FindTaskCommand e = (FindTaskCommand) other; + return input.equals(e.input); + } + + /** + * Provides an ordered list of tasks that contains keyword. + * + * @param list - the list of tasks that matches keyword + * @return String of ordered list of tasks. + */ + private String getOutput(ArrayList list) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + int order = i + 1; + if (i == list.size() - 1) { + sb.append(order).append(". ").append(list.get(i).toString()); + } else { + sb.append(order).append(". ").append(list.get(i).toString()).append("\n"); + } + } + return sb.toString(); + } +} + diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index afb02ee428f..e1f5a56542a 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -15,6 +15,7 @@ import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindTaskCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -76,6 +77,9 @@ public Command parseCommand(String userInput) throws ParseException { case DeleteTaskCommand.COMMAND_WORD: return new DeleteTaskCommandParser().parse(arguments); + case FindTaskCommand.COMMAND_WORD: + return new FindTaskCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java new file mode 100644 index 00000000000..023781a0d7b --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java @@ -0,0 +1,21 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; + +import seedu.address.logic.commands.FindTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +public class FindTaskCommandParser implements Parser { + + /** + * Parses the given {@code String} of argument in the context of the FindTaskCommand + * and returns a FindTaskCommand object for execution. + * @throws ParseException if the user input does not conform to the expected format + */ + public FindTaskCommand parse(String args) throws ParseException { + requireNonNull(args); + return new FindTaskCommand(args); + } + + } + diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index c43e25752e9..36bc75cd850 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -1,6 +1,7 @@ package seedu.address.model; import java.nio.file.Path; +import java.util.ArrayList; import java.util.function.Predicate; import javafx.collections.ObservableList; @@ -91,4 +92,10 @@ public interface Model { TaskList getTaskList(); void deleteTask(Integer taskNumber); + + /** + * finds tasks based on keyword. + * filters task list based on matching keyword {@code input}. + */ + ArrayList findTask(String input); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 96747b91701..81e1fb9024d 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -4,6 +4,7 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.nio.file.Path; +import java.util.ArrayList; import java.util.function.Predicate; import java.util.logging.Logger; @@ -170,4 +171,11 @@ public TaskList getTaskList() { public void deleteTask(Integer taskNumber) { taskList.deleteTask(taskNumber); } + + //=========== Find Task ================================================================================== + + @Override + public ArrayList findTask(String input) { + return taskList.findTask(input); + } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index eb657c9f29a..c353cac7df0 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -26,4 +26,18 @@ public int size() { public void deleteTask(Integer taskNumber) { taskList.remove(taskNumber - 1); // to convert to zero-based indexing } + + public ArrayList findTask(String input) { + ArrayList matchingTasks = new ArrayList<>(); + for (int i = 0; i < this.taskList.size(); i++) { + Task curr = this.taskList.get(i); + if (curr.toString().contains(input)) { + matchingTasks.add(curr); + } + } + return matchingTasks; + } + } + + diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 242d7a1c2e2..459ec7d6fff 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -3,6 +3,7 @@ import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; +import java.util.ArrayList; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -116,5 +117,9 @@ public TaskList getTaskList() { public void deleteTask(Integer taskNumber) { throw new AssertionError("This method should not be called"); } + + @Override + public ArrayList findTask(String input) {throw new AssertionError("This method should not be called."); } } + } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index ea8e261349c..46f8f535cad 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -3,6 +3,7 @@ import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; +import java.util.ArrayList; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -110,5 +111,8 @@ public void deleteTask(Integer taskNumber) { public TaskList getTaskList() { throw new AssertionError("This method should not be called."); } + + @Override + public ArrayList findTask(String input) {throw new AssertionError("This method should not be called."); } } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java new file mode 100644 index 00000000000..6ad9f00fe1a --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -0,0 +1,130 @@ +package seedu.address.logic.commands; + +import static seedu.address.testutil.Assert.assertThrows; + + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.function.Predicate; + + +import org.junit.jupiter.api.Test; + +import javafx.collections.ObservableList; +import seedu.address.commons.core.GuiSettings; +import seedu.address.model.Model; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; +import seedu.address.model.person.Person; +import seedu.address.model.task.Task; + +/** + * Contains integration tests (interaction with the Model) for {@code FindCommand}. + */ +public class FindTaskCommandTest { + + @Test + public void constructor_nullDescription_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new AddTaskCommand(null)); + } + + @Test + public void constructor_nullDescriptionAndDeadline_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new AddTaskCommand(null, null)); + } + + /** + * A default model stub that have all the methods failing. + */ + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addTask(Task task) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteTask(Integer taskNumber) { + throw new AssertionError("This method should not be called."); + } + + @Override + public TaskList getTaskList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public ArrayList findTask(String input) { throw new AssertionError("This method should not be called."); } + } +} + From 730bfe76a3883140a4de963fdfff00cc57349481 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Sun, 13 Mar 2022 17:19:04 +0800 Subject: [PATCH 025/140] Edit CheckStyle --- .../logic/commands/FindTaskCommand.java | 19 ++++++++--------- .../logic/parser/AddressBookParser.java | 2 +- .../logic/parser/FindTaskCommandParser.java | 21 +++++++++---------- .../java/seedu/address/model/TaskList.java | 6 ++++++ .../logic/commands/AddCommandTest.java | 4 ++++ .../logic/commands/AddTaskCommandTest.java | 3 ++- .../logic/commands/DeleteTaskCommandTest.java | 3 ++- .../logic/commands/FindTaskCommandTest.java | 5 ++--- 8 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/FindTaskCommand.java b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java index eb642572094..80655c3dafa 100644 --- a/src/main/java/seedu/address/logic/commands/FindTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java @@ -3,7 +3,6 @@ import static java.util.Objects.requireNonNull; - import java.util.ArrayList; import seedu.address.logic.commands.exceptions.CommandException; @@ -33,7 +32,7 @@ public class FindTaskCommand extends Command { /** * Initializes a FindTaskCommand with the given input. */ - public FindTaskCommand(String input){ + public FindTaskCommand(String input) { requireNonNull(input); this.input = input; } @@ -81,15 +80,15 @@ public boolean equals(Object other) { */ private String getOutput(ArrayList list) { StringBuilder sb = new StringBuilder(); - for (int i = 0; i < list.size(); i++) { - int order = i + 1; - if (i == list.size() - 1) { - sb.append(order).append(". ").append(list.get(i).toString()); - } else { - sb.append(order).append(". ").append(list.get(i).toString()).append("\n"); - } + for (int i = 0; i < list.size(); i++) { + int order = i + 1; + if (i == list.size() - 1) { + sb.append(order).append(". ").append(list.get(i).toString()); + } else { + sb.append(order).append(". ").append(list.get(i).toString()).append("\n"); } - return sb.toString(); } + return sb.toString(); + } } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index e1f5a56542a..e6140c5c001 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -78,7 +78,7 @@ public Command parseCommand(String userInput) throws ParseException { return new DeleteTaskCommandParser().parse(arguments); case FindTaskCommand.COMMAND_WORD: - return new FindTaskCommandParser().parse(arguments); + return new FindTaskCommandParser().parse(arguments); default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java index 023781a0d7b..6703cfd11a3 100644 --- a/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java @@ -7,15 +7,14 @@ public class FindTaskCommandParser implements Parser { - /** - * Parses the given {@code String} of argument in the context of the FindTaskCommand - * and returns a FindTaskCommand object for execution. - * @throws ParseException if the user input does not conform to the expected format - */ - public FindTaskCommand parse(String args) throws ParseException { - requireNonNull(args); - return new FindTaskCommand(args); - } - - } + /** + * Parses the given {@code String} of argument in the context of the FindTaskCommand + * and returns a FindTaskCommand object for execution. + * @throws ParseException if the user input does not conform to the expected format + */ + public FindTaskCommand parse(String args) throws ParseException { + requireNonNull(args); + return new FindTaskCommand(args); + } +} diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index c353cac7df0..0966f2b5efd 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -27,6 +27,12 @@ public void deleteTask(Integer taskNumber) { taskList.remove(taskNumber - 1); // to convert to zero-based indexing } + /** + * Returns an ArrayList of matching tasks based on keyword. + * + * @param input the keyword input by user + * @return the list of tasks that contains the keyword + */ public ArrayList findTask(String input) { ArrayList matchingTasks = new ArrayList<>(); for (int i = 0; i < this.taskList.size(); i++) { diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 12a7f1ae382..9590addb0cf 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -164,6 +164,10 @@ public TaskList getTaskList() { public void deleteTask(Integer taskNumber) { throw new AssertionError("This method should not be called."); } + + @Override + public ArrayList findTask(String input) { + throw new AssertionError("This method should not be called."); } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 459ec7d6fff..9862be23f7e 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -119,7 +119,8 @@ public void deleteTask(Integer taskNumber) { } @Override - public ArrayList findTask(String input) {throw new AssertionError("This method should not be called."); } + public ArrayList findTask(String input) { + throw new AssertionError("This method should not be called."); } } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 46f8f535cad..483f8d2a843 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -113,6 +113,7 @@ public TaskList getTaskList() { } @Override - public ArrayList findTask(String input) {throw new AssertionError("This method should not be called."); } + public ArrayList findTask(String input) { + throw new AssertionError("This method should not be called."); } } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 6ad9f00fe1a..0fc9680c36c 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -2,12 +2,10 @@ import static seedu.address.testutil.Assert.assertThrows; - import java.nio.file.Path; import java.util.ArrayList; import java.util.function.Predicate; - import org.junit.jupiter.api.Test; import javafx.collections.ObservableList; @@ -124,7 +122,8 @@ public TaskList getTaskList() { } @Override - public ArrayList findTask(String input) { throw new AssertionError("This method should not be called."); } + public ArrayList findTask(String input) { + throw new AssertionError("This method should not be called."); } } } From 06aa8e6bb47413d3cc785aab3f5feb574b2e554f Mon Sep 17 00:00:00 2001 From: yumengtan Date: Sun, 13 Mar 2022 21:56:49 +0800 Subject: [PATCH 026/140] Edit find Command --- .../logic/commands/FindTaskCommand.java | 41 +++++-------------- src/main/java/seedu/address/model/Model.java | 3 +- .../seedu/address/model/ModelManager.java | 3 +- .../java/seedu/address/model/TaskList.java | 27 ++++++++++-- .../logic/commands/AddCommandTest.java | 2 +- .../logic/commands/AddTaskCommandTest.java | 3 +- .../logic/commands/DeleteTaskCommandTest.java | 3 +- .../logic/commands/FindTaskCommandTest.java | 3 +- 8 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/FindTaskCommand.java b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java index 80655c3dafa..5f3092471c0 100644 --- a/src/main/java/seedu/address/logic/commands/FindTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindTaskCommand.java @@ -3,11 +3,8 @@ import static java.util.Objects.requireNonNull; -import java.util.ArrayList; - import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.task.Task; /** * finds a task to the system based on user input. @@ -23,9 +20,9 @@ public class FindTaskCommand extends Command { public static final String MESSAGE_ARGUMENTS = "Here are the matching tasks in the list:\n" + "%1$s"; - public static final String MESSAGE_NO_DESCRIPTION = "Unable to find any matching tasks due to empty keyword"; + public static final String MESSAGE_NO_DESCRIPTION = "Unable to find any matching tasks due to empty keyword!"; - public static final String MESSAGE_NO_MATCHING_TASK = "Unable to find any matching tasks based on input"; + public static final String MESSAGE_NO_MATCHING_TASK = "Unable to find any matching tasks based on input!"; private final String input; @@ -43,17 +40,16 @@ public CommandResult execute(Model model) throws CommandException { if (this.input.equals("")) { throw new CommandException(MESSAGE_NO_DESCRIPTION + "\n" + MESSAGE_USAGE); } - ArrayList matchingList = model.findTask(input); - String output = getOutput(matchingList); + try { + String orderedList = model.findTask(input); - if (matchingList.size() == 0) { + if (orderedList.isEmpty()) { + throw new CommandException(MESSAGE_NO_MATCHING_TASK); + } + return new CommandResult(String.format(MESSAGE_ARGUMENTS, orderedList)); + } catch (CommandException e) { throw new CommandException(MESSAGE_NO_MATCHING_TASK); } - - // Ensure that tasklist is not changed, to be deleted later - System.out.println(model.findTask(input).toString()); - - return new CommandResult(String.format(MESSAGE_ARGUMENTS, output)); } @Override @@ -72,23 +68,6 @@ public boolean equals(Object other) { return input.equals(e.input); } - /** - * Provides an ordered list of tasks that contains keyword. - * - * @param list - the list of tasks that matches keyword - * @return String of ordered list of tasks. - */ - private String getOutput(ArrayList list) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < list.size(); i++) { - int order = i + 1; - if (i == list.size() - 1) { - sb.append(order).append(". ").append(list.get(i).toString()); - } else { - sb.append(order).append(". ").append(list.get(i).toString()).append("\n"); - } - } - return sb.toString(); - } + } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 36bc75cd850..0d0daa820e4 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -1,7 +1,6 @@ package seedu.address.model; import java.nio.file.Path; -import java.util.ArrayList; import java.util.function.Predicate; import javafx.collections.ObservableList; @@ -97,5 +96,5 @@ public interface Model { * finds tasks based on keyword. * filters task list based on matching keyword {@code input}. */ - ArrayList findTask(String input); + String findTask(String input); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 81e1fb9024d..d0878c0db66 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -4,7 +4,6 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.nio.file.Path; -import java.util.ArrayList; import java.util.function.Predicate; import java.util.logging.Logger; @@ -175,7 +174,7 @@ public void deleteTask(Integer taskNumber) { //=========== Find Task ================================================================================== @Override - public ArrayList findTask(String input) { + public String findTask(String input) { return taskList.findTask(input); } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 0966f2b5efd..945fa65771e 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -31,19 +31,38 @@ public void deleteTask(Integer taskNumber) { * Returns an ArrayList of matching tasks based on keyword. * * @param input the keyword input by user - * @return the list of tasks that contains the keyword + * @return the list of ordered tasks that contain the keyword */ - public ArrayList findTask(String input) { + public String findTask(String input) { ArrayList matchingTasks = new ArrayList<>(); for (int i = 0; i < this.taskList.size(); i++) { Task curr = this.taskList.get(i); - if (curr.toString().contains(input)) { + if (curr.toString().matches("(?i).*" + input + ".*")) { //bypass case sensitivity with regex matchingTasks.add(curr); } } - return matchingTasks; + String orderedList = getOutput(matchingTasks); + return orderedList; } + /** + * Provides an ordered list of tasks that contains keyword. + * + * @param list - the list of tasks that matches keyword + * @return String of ordered list of tasks. + */ + private String getOutput(ArrayList list) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + int order = i + 1; + if (i == list.size() - 1) { + sb.append(order).append(". ").append(list.get(i).toString()); + } else { + sb.append(order).append(". ").append(list.get(i).toString()).append("\n"); + } + } + return sb.toString(); + } } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 9590addb0cf..e68040431e0 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -166,7 +166,7 @@ public void deleteTask(Integer taskNumber) { } @Override - public ArrayList findTask(String input) { + public String findTask(String input) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 9862be23f7e..524d861692d 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -3,7 +3,6 @@ import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; -import java.util.ArrayList; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -119,7 +118,7 @@ public void deleteTask(Integer taskNumber) { } @Override - public ArrayList findTask(String input) { + public String findTask(String input) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 483f8d2a843..2553f86ab2c 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -3,7 +3,6 @@ import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; -import java.util.ArrayList; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -113,7 +112,7 @@ public TaskList getTaskList() { } @Override - public ArrayList findTask(String input) { + public String findTask(String input) { throw new AssertionError("This method should not be called."); } } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 0fc9680c36c..2db1445d0ec 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -3,7 +3,6 @@ import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; -import java.util.ArrayList; import java.util.function.Predicate; import org.junit.jupiter.api.Test; @@ -122,7 +121,7 @@ public TaskList getTaskList() { } @Override - public ArrayList findTask(String input) { + public String findTask(String input) { throw new AssertionError("This method should not be called."); } } } From e28956cf44eeb99ce054b07e151057de31cb9d6c Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 15 Mar 2022 14:43:14 +0800 Subject: [PATCH 027/140] Update UG, DG and PPP --- docs/DeveloperGuide.md | 11 +++++++++-- docs/UserGuide.md | 10 +++++----- docs/team/putaojuice.md | 29 +++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 18ec0890081..c67fba31192 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -314,8 +314,9 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli **MSS** -1. User requests to add a task with add task command -2. NUScheduler adds the user's defined task to the task list +1. User add a task with add task command +2. NUScheduler provide feedback based on the user input. +3. NUScheduler adds the user's defined task to the task list Use case ends. @@ -331,6 +332,11 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli Use case ends. +* 2c. The task has multiple description prefix (`d/`) or deadline prefix (`t/`). + * 2c1. NUScheduler shows an error message. + + Use case ends. + **Use case: Delete a task** **MSS** @@ -414,6 +420,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * **Private contact detail**: A contact detail that is not meant to be shared with others * **Task**: A task with descriptions and/or deadline * **Task list**: A task list of all the tasks +* **Prefix**: A header (eg `d/`, `t/`) that is used to identify different clauses in user inputs. -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5e799a13865..729e9c20d7c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -70,13 +70,13 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona -### Feature - Add a task: `add t` +### Feature - Add a task: `addt` Adds a task to the task list. -Format: `add t /DESCRIPTION /DEADLINE [/TAG]` +Format: `addt d/DESCRIPTION [t/DEADLINE]` -Example: `add t /Buy groceries /2022 02 22 5pm [/Important]` +Example: `addt d/Buy groceries [t/2022 02 22 5pm]` ### Feature - Delete a task: `delt ` @@ -200,7 +200,7 @@ data of your previous NUScheduler home folder. Action | Format, Examples --------|------------------ -**add t** | `add t /DESCRIPTION /DEADLINE [/TAG]`
e.g., `add t /Buy groceries /2022 02 22 5pm /Important` +**addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` **delt ** | `del t `
e.g., `del t 3` **upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` **upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` @@ -211,4 +211,4 @@ Action | Format, Examples **upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` **view c** | `view c [to] [t] [/TAG]`
e.g., `view c` **remind** | `remind []`
e.g., `remind 10` -**exit** | `exit` +**exit** | `exit` diff --git a/docs/team/putaojuice.md b/docs/team/putaojuice.md index 42f19b2e621..e61a893ba4d 100644 --- a/docs/team/putaojuice.md +++ b/docs/team/putaojuice.md @@ -9,25 +9,38 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona Given below are my contributions to the project. -* **New Feature**: - * to be added soon - -* **New Feature**: - * to be added soon +* **New Feature**: Implemented `AddTask` command. + * What it does: Allow the user to add a task to the application with description and deadline (optional) + * Justification: Our target audience is year 1 computing students. It helps them to keep track of their assignments + and any other daily tasks. + * **Classes created**: + * `AddTaskCommand` + * `AddTaskCommandParser` + * `TaskList` + * `Task` + * **Tests written**: + * `AddTaskCommandTest` + * **Additional info**: + * `Task` and `TaskList` classes are created to capture the information of tasks and store them as an `ArrayList` in + `ModelManager`. * **Code contributed**: [RepoSense link (to be added soon)]() * **Project management**: - * to be added soon + * Managed release `v1.1`, `v1.2`. + * Organised weekly project meeting and set up weekly milestone. + * Reviewed pull requests. * **Enhancements to existing features**: * to be added soon * **Documentation**: * User Guide: - * to be added soon + * Added documentation for the feature `AddTask`. * Developer Guide: - * to be added soon + * Added various non-functional requirement in the developer guide. + * Contribute to glossary in the developer guide. + * Added MSS for `AddTask`. * **Community**: * to be added soon From 96dad77b5736693d25d390f2c99b3b260874c646 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 16 Mar 2022 23:24:11 +0800 Subject: [PATCH 028/140] Update UG, DG and PPP based on implementation --- docs/DeveloperGuide.md | 34 ++++++++++++++++++---------------- docs/UserGuide.md | 41 +++++++++++++++++++++++++++-------------- docs/team/yumengtan.md | 22 +++++++++++++++++----- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c67fba31192..514db55bd48 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -266,20 +266,22 @@ NUScheduler is for Year 1 NUS Computing students who prefer CLI over GUI and has Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| Priority | As a …​ | I want to …​ | So that I can…​ | -|----------| ------------------------------------------ | ------------------------------------ | ------------------------------------------------------------------ | -| `* * *` | beginner user | add a task | keep track of the task | -| `* * *` | beginner user | delete a task | remove a task I have completed | -| `* * *` | beginner user | edit a task | change details of a task | -| `* * *` | beginner user | view all tasks | keep track of all my current tasks | -| `* * *` | beginner user | add a contact | keep track of all my contacts | -| `* * *` | beginner user | delete a contact | delete an incorrect/unneeded contact | -| `* * *` | beginner user | edit a contact | correct/update a a contact | -| `* * *` | beginner user | view all contacts | view all my current contacts | -| `* * *` | beginner user | add a label | know which task is for which module | -| `* * *` | potential user | use simple commands | learn the commands easily | -| `* * *` | year 1 computing student | keep track of assignment deadlines | complete the tasks on time | -| `*` | beginner user | see a reminder of tasks from the app | know what are my upcoming deadlines | +| Priority | As a …​ | I want to …​ | So that I can…​ | +|----------|--------------------------|--------------------------------------|--------------------------------------| +| `* * *` | beginner user | add a task | keep track of the task | +| `* * *` | beginner user | delete a task | remove a task I have completed | +| `* * *` | beginner user | edit a task | change details of a task | +| `* * *` | beginner user | view all tasks | keep track of all my current tasks | +| `* * *` | beginner user | add a contact | keep track of all my contacts | +| `* * *` | beginner user | delete a contact | delete an incorrect/unneeded contact | +| `* * *` | beginner user | edit a contact | correct/update a a contact | +| `* * *` | beginner user | find tasks based on keyword | search for relevant tasks quickly | +| `* * *` | beginner user | find contacts based on keyword | search for relevant contacts quickly | +| `* * *` | beginner user | view all contacts | view all my current contacts | +| `* * *` | beginner user | add a label | know which task is for which module | +| `* * *` | potential user | use simple commands | learn the commands easily | +| `* * *` | year 1 computing student | keep track of assignment deadlines | complete the tasks on time | +| `*` | beginner user | see a reminder of tasks from the app | know what are my upcoming deadlines | *{More to be added}* @@ -374,12 +376,12 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli Use case ends. -**Use case: Find a task** +**Use case: Find tasks** **MSS** 1. User requests to find tasks with find command -2. NUScheduler shows a list of tasks from task list. +2. NUScheduler provides a list of matching tasks from the task list. Use case ends. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 729e9c20d7c..8afa7eac439 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,6 +110,18 @@ Format: `label t tag` Example: `label t 3 important` +### Feature - Find tasks: `findt KEYWORD` + +Locating tasks which match any of given keywords. + +Format:  `findt KEYWORD` + +- The search is case-insensitive. e.g. `lessons` will match `Lessons`. +- The order of the keywords does not matter. e.g. `drink water` will match `water drink` +- Choice of either full words matched or any tasks containing keyword. + +Example: `findt lessons` returns `Swimming lessons 03/05/2022`. + ### Feature - View all tasks: `view t` View all the tasks currently in the task list. @@ -198,17 +210,18 @@ data of your previous NUScheduler home folder. ## Command summary -Action | Format, Examples ---------|------------------ -**addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` -**delt ** | `del t `
e.g., `del t 3` -**upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` -**upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` -**lab t ** | `label t tag`
e.g., `label t 3 important` -**view t** | `view t` -**add c** | `add c /NAME /EMAIL /TELEGRAM [/TAG]`
e.g., `add c /Betsy Crow /betsycrow@example.com /betsyc /Group Member` -**del c ** | `del c `
e.g., `del c 3` -**upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` -**view c** | `view c [to] [t] [/TAG]`
e.g., `view c` -**remind** | `remind []`
e.g., `remind 10` -**exit** | `exit` +| Action | Format, Examples | +|-----------------------|-------------------------------------------------------------------------------------------------------------------| +| **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | +| **delt ** | `del t `
e.g., `del t 3` | +| **upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` | +| **upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` | +| **findt KEYWORD** | `findt `
e.g., `findt lessons` | +| **lab t ** | `label t tag`
e.g., `label t 3 important` | +| **view t** | `view t` | +| **add c** | `add c /NAME /EMAIL /TELEGRAM [/TAG]`
e.g., `add c /Betsy Crow /betsycrow@example.com /betsyc /Group Member` | +| **del c ** | `del c `
e.g., `del c 3` | +| **upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` | +| **view c** | `view c [to] [t] [/TAG]`
e.g., `view c` | +| **remind** | `remind []`
e.g., `remind 10` | +| **exit** | `exit` | diff --git a/docs/team/yumengtan.md b/docs/team/yumengtan.md index 42c95d53455..8c94c0f81f6 100644 --- a/docs/team/yumengtan.md +++ b/docs/team/yumengtan.md @@ -9,8 +9,16 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona Given below are my contributions to the project. -* **New Feature**: - * to be added soon +* **New Feature**: Implemented `FindTask` command. + * What it does: Allow the user to find matching tasks in task list based on keyword/ + * Justification: Our target audience is year 1 computing students. It helps them find any tasks easily based on keyword. + * **Classes created**: + * `FindTaskCommand` + * `FindTaskCommandParser` + * **Tests Written**: + * `FindTaskCommandTest` + * **Additional info**: + * Used regex to ignore case sensitivity from user input. * **New Feature**: * to be added soon @@ -18,16 +26,20 @@ Given below are my contributions to the project. * **Code contributed**: [RepoSense link (to be added soon)]() * **Project management**: - * to be added soon + * Managed release `v1.1`, `v1.2`. + * Participated in weekly project meetings and set up weekly milestones with the team. + * Reviewed pull requests. * **Enhancements to existing features**: * to be added soon * **Documentation**: * User Guide: - * to be added soon + * Added documentation for the feature `FindTask`. * Developer Guide: - * to be added soon + * Contribute to glossary in the developer guide. + * Added user story for find task feature. + * Added MSS for `FindTask`. * **Community**: * to be added soon From d0b3a319109531cc98bf76e8fa0b5894bc968168 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Fri, 18 Mar 2022 02:20:59 +0800 Subject: [PATCH 029/140] Add more tests for add task command - Add more tests for AddTaskCommandTest - Add AddTaskCommandParserTest --- .../logic/parser/AddTaskCommandParser.java | 4 ++ .../logic/commands/AddTaskCommandTest.java | 35 ++++++++++++ .../parser/AddTaskCommandParserTest.java | 54 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index ab393764b60..03e4815f1f5 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -41,6 +41,10 @@ public AddTaskCommand parse(String args) throws ParseException { String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + if (description.equals("")) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + if (deadline.equals("")) { // task without deadline set return new AddTaskCommand(description); diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 524d861692d..2b73283993e 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -1,5 +1,7 @@ package seedu.address.logic.commands; +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; import static seedu.address.testutil.Assert.assertThrows; import java.nio.file.Path; @@ -28,6 +30,25 @@ public void constructor_nullDescriptionAndDeadline_throwsNullPointerException() assertThrows(NullPointerException.class, () -> new AddTaskCommand(null, null)); } + @Test + public void execute_addTaskNoDeadline_addSuccessful() throws Exception { + ModelStubAcceptTask modelStubAcceptTask = new ModelStubAcceptTask(); + + CommandResult commandResult = new AddTaskCommand("description").execute(modelStubAcceptTask); + assertEquals(String.format(AddTaskCommand.MESSAGE_ARGUMENTS, "description", "No deadline set"), + commandResult.getFeedbackToUser()); + } + + @Test + public void execute_addTaskWithDeadline_addSuccessful() throws Exception { + ModelStubAcceptTask modelStubAcceptTask = new ModelStubAcceptTask(); + + CommandResult commandResult = new AddTaskCommand("description", "2022") + .execute(modelStubAcceptTask); + assertEquals(String.format(AddTaskCommand.MESSAGE_ARGUMENTS, "description", "2022"), + commandResult.getFeedbackToUser()); + } + /** * A default model stub that have all of the methods failing. */ @@ -122,4 +143,18 @@ public String findTask(String input) { throw new AssertionError("This method should not be called."); } } + private class ModelStubAcceptTask extends ModelStub { + private TaskList taskList = new TaskList(); + + @Override + public TaskList getTaskList() { + return taskList; + } + + @Override + public void addTask(Task task) { + requireNonNull(task); + taskList.addTask(task); + } + } } diff --git a/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java new file mode 100644 index 00000000000..57f6a4066a4 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java @@ -0,0 +1,54 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.commands.AddTaskCommand; + +public class AddTaskCommandParserTest { + private AddTaskCommandParser parser = new AddTaskCommandParser(); + + @Test + public void parse_allFieldPresent_success() { + assertParseSuccess(parser, "addt d/description t/2022", + new AddTaskCommand("description", "2022")); + } + + @Test + public void parse_optionalFieldsMissing_success() { + assertParseSuccess(parser, "addt d/description", + new AddTaskCommand("description")); + } + + @Test + public void parse_multipleDescriptions_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + assertParseFailure(parser, "addt d/abc d/abc", expectedMessage); + } + + @Test + public void parse_multipleDeadline_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + assertParseFailure(parser, "addt d/abc t/2022 t/2022", expectedMessage); + } + + @Test + public void parse_compulsoryFieldMissing_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + + // has description prefix + assertParseFailure(parser, "addt d/", expectedMessage); + + // no description prefix + assertParseFailure(parser, "addt", expectedMessage); + } + + @Test + public void parse_invalidDeadlineFormat_failure() { + // TODO to be added when implementing DateTimeFormatter + } + +} From f92813202f5a8ee2a579e575f874d853e84c1653 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:42:55 +0800 Subject: [PATCH 030/140] Add tests for Task and TaskList - Test Task constructor - Test Task toString() - Test TaskList constructor - Test TaskList addTask() --- .../java/seedu/address/model/TaskList.java | 13 ++++++++ .../java/seedu/address/model/task/Task.java | 4 +++ .../seedu/address/model/TaskListTest.java | 33 +++++++++++++++++++ .../seedu/address/model/task/TaskTest.java | 30 +++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 src/test/java/seedu/address/model/TaskListTest.java create mode 100644 src/test/java/seedu/address/model/task/TaskTest.java diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 945fa65771e..f42caec389f 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -1,5 +1,7 @@ package seedu.address.model; +import static java.util.Objects.requireNonNull; + import java.util.ArrayList; import seedu.address.model.task.Task; @@ -11,10 +13,21 @@ public TaskList() { this.taskList = new ArrayList<>(); } + /** + * Add a task to the taskList. + * + * @param task the Task to be added which must not be null + */ public void addTask(Task task) { + requireNonNull(task); this.taskList.add(task); } + /** + * Returns the taskList. + * + * @return the taskList with all the tasks contained + */ public ArrayList getTaskList() { return this.taskList; } diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 4cb63b71688..501f312da14 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -1,5 +1,7 @@ package seedu.address.model.task; +import static java.util.Objects.requireNonNull; + public class Task { private final String description; private final String deadline; @@ -8,6 +10,8 @@ public class Task { * Initializes a Task with a description and deadline. */ public Task(String description, String deadline) { + requireNonNull(description); + requireNonNull(deadline); this.description = description; this.deadline = deadline; } diff --git a/src/test/java/seedu/address/model/TaskListTest.java b/src/test/java/seedu/address/model/TaskListTest.java new file mode 100644 index 00000000000..248a18ea49b --- /dev/null +++ b/src/test/java/seedu/address/model/TaskListTest.java @@ -0,0 +1,33 @@ +package seedu.address.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.testutil.Assert.assertThrows; + +import java.util.ArrayList; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.task.Task; + +public class TaskListTest { + private final TaskList taskList = new TaskList(); + + @Test + public void constructor() { + assertEquals(Collections.emptyList(), taskList.getTaskList()); + } + + @Test + public void addTask_success() { + ArrayList stubTaskList = new ArrayList<>(); + stubTaskList.add(new Task("description", "2022")); + taskList.addTask(new Task("description", "2022")); + assertEquals(stubTaskList.toString(), taskList.getTaskList().toString()); + } + + @Test + public void addTask_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> taskList.addTask(null)); + } +} diff --git a/src/test/java/seedu/address/model/task/TaskTest.java b/src/test/java/seedu/address/model/task/TaskTest.java new file mode 100644 index 00000000000..26f91c77440 --- /dev/null +++ b/src/test/java/seedu/address/model/task/TaskTest.java @@ -0,0 +1,30 @@ +package seedu.address.model.task; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.testutil.Assert.assertThrows; + +import org.junit.jupiter.api.Test; + +public class TaskTest { + + @Test + public void constructor_allNull_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new Task(null, null)); + } + + @Test + public void constructor_descriptionNull_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new Task(null, "2022")); + } + + @Test + public void constructor_deadlineNull_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new Task("description", null)); + } + + @Test + public void toString_success() { + Task task = new Task("description", "2022"); + assertEquals(task.toString(), "Task: description 2022"); + } +} From 38438bcf662ddd8f7d24d15c38c0352e84aef1c1 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Sat, 19 Mar 2022 21:12:58 +0800 Subject: [PATCH 031/140] Update files to reflect project details of NUScheduler. Files updated: README.md - add codecov badge index.md - update to reflect project details _base.scss - update to reflect project details --- README.md | 3 ++- docs/_sass/minima/_base.scss | 2 +- docs/index.md | 13 ++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index de367eef77b..f1cd21b53e3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) +[![CI Status](https://github.com/AY2122S2-CS2103-F11-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) +[![codecov](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp/branch/master/graph/badge.svg?token=G5ITTT4UTJ)](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp) ![Ui](docs/images/Ui.png) # NUScheduler diff --git a/docs/_sass/minima/_base.scss b/docs/_sass/minima/_base.scss index 0d3f6e80ced..a91e07f732e 100644 --- a/docs/_sass/minima/_base.scss +++ b/docs/_sass/minima/_base.scss @@ -288,7 +288,7 @@ table { text-align: center; } .site-header:before { - content: "AB-3"; + content: "NUScheduler"; font-size: 32px; } } diff --git a/docs/index.md b/docs/index.md index a47f0cc2093..3342c15f51c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,16 +1,19 @@ --- layout: page -title: AddressBook Level-3 +title: NUScheduler --- -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/AY2122S2-CS2103-F11-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) [![codecov](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp/branch/master/graph/badge.svg?token=G5ITTT4UTJ)](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp) ![Ui](images/Ui.png) -**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). +**NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts**, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. -* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). -* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. + +* If you are interested in using NUScheduler, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). +* If you are interested about developing NUScheduler, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. **Acknowledgements** From 1df055d851ddf6af9730be847408b8823f16a489 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Sun, 20 Mar 2022 02:04:34 +0800 Subject: [PATCH 032/140] Update on AddTaskCommandParser - Add DateTimeFormatter in AddTaskParser - Add tests for the usage of DateTimeFormatter - Refactor AddTaskCommandParser --- .../logic/commands/AddTaskCommand.java | 4 +- .../logic/parser/AddTaskCommandParser.java | 73 ++++++++++++++++--- .../parser/AddTaskCommandParserTest.java | 40 ++++++++-- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/AddTaskCommand.java b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java index bb61673579f..bb9bf6aa204 100644 --- a/src/main/java/seedu/address/logic/commands/AddTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddTaskCommand.java @@ -15,8 +15,8 @@ public class AddTaskCommand extends Command { public static final String COMMAND_WORD = "addt"; public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Add a task with description and/or deadline. \n" - + "Format: addt d/[DESCRIPTION] t/[DEADLINE]\n" + + ": Add a task with description and/or deadline.\n" + + "Format: addt d/DESCRIPTION [t/DEADLINE (dd/mm/yyyy)]\n" + "Example: " + COMMAND_WORD + " " + PREFIX_ADD_TASK_DESCRIPTION + "Swimming lesson " + PREFIX_ADD_TASK_DEADLINE + "03/05/2022"; diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index 03e4815f1f5..0501f592c2a 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -5,6 +5,8 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.List; import seedu.address.logic.commands.AddTaskCommand; @@ -25,26 +27,21 @@ public AddTaskCommand parse(String args) throws ParseException { PREFIX_ADD_TASK_DEADLINE); try { - List description = argMultimap.getAllValues(PREFIX_ADD_TASK_DESCRIPTION); - List deadline = argMultimap.getAllValues(PREFIX_ADD_TASK_DEADLINE); + // Throw exception if more than 1 description or deadline prefix exists + checkMultiplePrefixTokens(argMultimap); - if (description.size() > 1 || deadline.size() > 1) { - // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); - } + // Throw exception if user input does not contain any description prefix + checkDescriptionPrefixEmpty(argMultimap); + + // Throw exception if deadline does not adhere to specified format + checkDeadlineFormat(argMultimap); } catch (ParseException e) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); } - //TODO try-catch block for deadline input has to be formatted - String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); - if (description.equals("")) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); - } - if (deadline.equals("")) { // task without deadline set return new AddTaskCommand(description); @@ -53,4 +50,56 @@ public AddTaskCommand parse(String args) throws ParseException { return new AddTaskCommand(description, deadline); } } + + /** + * Check if more than 1 description or deadline prefix token exists in user input. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if more than 1 of the same prefix exists + */ + private void checkMultiplePrefixTokens(ArgumentMultimap argMultimap) throws ParseException { + List description = argMultimap.getAllValues(PREFIX_ADD_TASK_DESCRIPTION); + List deadline = argMultimap.getAllValues(PREFIX_ADD_TASK_DEADLINE); + + // Throw exception if more than 1 description or deadline token is used + if (description.size() > 1 || deadline.size() > 1) { + // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } + + /** + * Check if description prefix token exists in user input. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if description prefix token does not exist + */ + private void checkDescriptionPrefixEmpty(ArgumentMultimap argMultimap) throws ParseException { + String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); + if (description.equals("")) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } + + /** + * Check if user's deadline input follows dd/MM/yyyy format. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if deadline does not follow the specified format + */ + private void checkDeadlineFormat(ArgumentMultimap argMultimap) throws ParseException { + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + + // If deadline is empty, return immediately without checking the format + if (deadline.equals("")) { + return; + } + + try { + dateTimeFormatter.parse(deadline); + } catch (DateTimeParseException e) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } } diff --git a/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java index 57f6a4066a4..ede00c260b4 100644 --- a/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java @@ -13,8 +13,8 @@ public class AddTaskCommandParserTest { @Test public void parse_allFieldPresent_success() { - assertParseSuccess(parser, "addt d/description t/2022", - new AddTaskCommand("description", "2022")); + assertParseSuccess(parser, "addt d/description t/01/01/2022", + new AddTaskCommand("description", "01/01/2022")); } @Test @@ -32,7 +32,7 @@ public void parse_multipleDescriptions_failure() { @Test public void parse_multipleDeadline_failure() { String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); - assertParseFailure(parser, "addt d/abc t/2022 t/2022", expectedMessage); + assertParseFailure(parser, "addt d/abc t/01/01/2022 t/01/01/2022", expectedMessage); } @Test @@ -42,13 +42,43 @@ public void parse_compulsoryFieldMissing_failure() { // has description prefix assertParseFailure(parser, "addt d/", expectedMessage); + // has description prefix and deadline prefix + assertParseFailure(parser, "addt d/ t/", expectedMessage); + // no description prefix assertParseFailure(parser, "addt", expectedMessage); } @Test - public void parse_invalidDeadlineFormat_failure() { - // TODO to be added when implementing DateTimeFormatter + public void parse_deadlineFormat_success() { + assertParseSuccess(parser, "addt d/description t/01/01/2022", + new AddTaskCommand("description", "01/01/2022")); + } + + @Test + public void parse_deadlineFormat_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + + // no "/" between date, month, year + assertParseFailure(parser, "addt d/description t/01012022", expectedMessage); + + // uses "-" between date, month, year + assertParseFailure(parser, "addt d/description t/01-01-2022", expectedMessage); + } + + @Test + public void parse_deadlineFormatUseAlphabets_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + + assertParseFailure(parser, "addt d/description t/monday", expectedMessage); + assertParseFailure(parser, "addt d/description t/o1/o1/2o22", expectedMessage); } + @Test + public void parse_deadlineFormatUseSymbols_failure() { + String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + + assertParseFailure(parser, "addt d/description t/!@#$%^&*(){}[]|~`", expectedMessage); + assertParseFailure(parser, "addt d/description t/*10!2()22", expectedMessage); + } } From 056892a307f1acbc26fa9839eaee859dd4eafe0b Mon Sep 17 00:00:00 2001 From: Ivor Chua <77225277+ivorcmx@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:19:05 +0800 Subject: [PATCH 033/140] Set theme jekyll-theme-slate --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index fac10d78b89..21e8b0fee7b 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ title: "NUScheduler" -theme: minima +theme: jekyll-theme-slate header_pages: - UserGuide.md From 7976cf4bfe60b41a785b0fdbe1c2546634fe903d Mon Sep 17 00:00:00 2001 From: Ivor Chua <77225277+ivorcmx@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:23:23 +0800 Subject: [PATCH 034/140] Set theme jekyll-theme-cayman --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 21e8b0fee7b..09f4fbdb7db 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ title: "NUScheduler" -theme: jekyll-theme-slate +theme: jekyll-theme-cayman header_pages: - UserGuide.md From 34084abf99214427a4f44d8080973bee2b4bf051 Mon Sep 17 00:00:00 2001 From: Ivor Chua <77225277+ivorcmx@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:26:19 +0800 Subject: [PATCH 035/140] Set theme jekyll-theme-minimal --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 09f4fbdb7db..a2d571fbcae 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ title: "NUScheduler" -theme: jekyll-theme-cayman +theme: jekyll-theme-minimal header_pages: - UserGuide.md From 64a5852c0335a5d1fb7e572e1e210d02b3789f78 Mon Sep 17 00:00:00 2001 From: Ivor Chua <77225277+ivorcmx@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:27:24 +0800 Subject: [PATCH 036/140] Set theme jekyll-theme-cayman --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index a2d571fbcae..09f4fbdb7db 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ title: "NUScheduler" -theme: jekyll-theme-minimal +theme: jekyll-theme-cayman header_pages: - UserGuide.md From 8e658f97cf6f2c506ca0c5db2fd9a3708efed965 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 21 Mar 2022 16:27:41 +0800 Subject: [PATCH 037/140] Fix config.yml --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index fac10d78b89..09f4fbdb7db 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ title: "NUScheduler" -theme: minima +theme: jekyll-theme-cayman header_pages: - UserGuide.md From e4b5cc58cab5cffb1dc0fd9147bd2c9a8d625589 Mon Sep 17 00:00:00 2001 From: castryl Date: Mon, 21 Mar 2022 16:31:00 +0800 Subject: [PATCH 038/140] View task command --- docs/UserGuide.md | 4 +-- .../logic/commands/ViewTaskCommand.java | 31 +++++++++++++++++++ .../logic/parser/AddressBookParser.java | 16 +++------- src/main/java/seedu/address/model/Model.java | 2 ++ .../seedu/address/model/ModelManager.java | 6 ++++ .../java/seedu/address/model/TaskList.java | 15 +++++++++ .../java/seedu/address/model/task/Task.java | 2 +- 7 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/ViewTaskCommand.java diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8afa7eac439..a887aa717ac 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -122,11 +122,11 @@ Format:  `findt KEYWORD` Example: `findt lessons` returns `Swimming lessons 03/05/2022`. -### Feature - View all tasks: `view t` +### Feature - List all tasks: `viewt` View all the tasks currently in the task list. -Format: `view t` +Format: `viewt` ### Feature - Add contact: `add c` diff --git a/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java b/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java new file mode 100644 index 00000000000..ec8e1730520 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java @@ -0,0 +1,31 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; + +/** + * Lists all persons in the address book to the user. + */ +public class ViewTaskCommand extends Command { + + public static final String COMMAND_WORD = "viewt"; + + public static final String MESSAGE_SUCCESS = "Listed all tasks"; + + public static final String MESSAGE_NO_TASK = "No tasks found!"; + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + if (model.getTaskList().size() == 0) { + // No tasks + throw new CommandException(MESSAGE_NO_TASK); + }; + // Printing out the current items in task list to make sure the method work, should be removed later on +// System.out.println(model.getTaskList().getTaskList().toString()); + String message = model.viewTask(); + return new CommandResult(MESSAGE_SUCCESS + "\n" + message); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index e6140c5c001..a51445024a3 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -6,18 +6,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.AddTaskCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.DeleteTaskCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.FindTaskCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.*; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -80,6 +69,9 @@ public Command parseCommand(String userInput) throws ParseException { case FindTaskCommand.COMMAND_WORD: return new FindTaskCommandParser().parse(arguments); + case ViewTaskCommand.COMMAND_WORD: + return new ViewTaskCommand(); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 0d0daa820e4..5da537d9164 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -97,4 +97,6 @@ public interface Model { * filters task list based on matching keyword {@code input}. */ String findTask(String input); + + String viewTask(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index d0878c0db66..ffe4ef18c5e 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -177,4 +177,10 @@ public void deleteTask(Integer taskNumber) { public String findTask(String input) { return taskList.findTask(input); } + + //=========== View Task =============== + @Override + public String viewTask() { + return taskList.viewTask(); + } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 945fa65771e..e8cfdbf7f13 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -45,6 +45,21 @@ public String findTask(String input) { return orderedList; } + /** + * Returns a String of all tasks. + * + * @return the list of ordered tasks + */ + public String viewTask() { +// ArrayList tasks = new ArrayList<>(); +// for (int i = 0; i < this.taskList.size(); i++) { +// tasks.add(this.taskList.get(i)); +// } + + String orderedList = getOutput(taskList); + return orderedList; + } + /** * Provides an ordered list of tasks that contains keyword. * diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 4cb63b71688..4288105813c 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -16,4 +16,4 @@ public Task(String description, String deadline) { public String toString() { return "Task: " + this.description + " " + deadline; } -} +} \ No newline at end of file From e99f96d708402be169d86ad0e9cfd7bd170abb0e Mon Sep 17 00:00:00 2001 From: castryl Date: Mon, 21 Mar 2022 16:35:53 +0800 Subject: [PATCH 039/140] Updates to adhere to checkstyle --- .../address/logic/commands/ViewTaskCommand.java | 5 ++--- .../address/logic/parser/AddressBookParser.java | 14 +++++++++++++- src/main/java/seedu/address/model/TaskList.java | 5 ----- src/main/java/seedu/address/model/task/Task.java | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java b/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java index ec8e1730520..ea1edef845a 100644 --- a/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/ViewTaskCommand.java @@ -22,9 +22,8 @@ public CommandResult execute(Model model) throws CommandException { if (model.getTaskList().size() == 0) { // No tasks throw new CommandException(MESSAGE_NO_TASK); - }; - // Printing out the current items in task list to make sure the method work, should be removed later on -// System.out.println(model.getTaskList().getTaskList().toString()); + } + String message = model.viewTask(); return new CommandResult(MESSAGE_SUCCESS + "\n" + message); } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index a51445024a3..897071d3590 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -6,7 +6,19 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import seedu.address.logic.commands.*; +import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.AddTaskCommand; +import seedu.address.logic.commands.ClearCommand; +import seedu.address.logic.commands.Command; +import seedu.address.logic.commands.DeleteCommand; +import seedu.address.logic.commands.DeleteTaskCommand; +import seedu.address.logic.commands.EditCommand; +import seedu.address.logic.commands.ExitCommand; +import seedu.address.logic.commands.FindCommand; +import seedu.address.logic.commands.FindTaskCommand; +import seedu.address.logic.commands.HelpCommand; +import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.ViewTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; /** diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index ebeb517e507..7b5309f1320 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -64,11 +64,6 @@ public String findTask(String input) { * @return the list of ordered tasks */ public String viewTask() { -// ArrayList tasks = new ArrayList<>(); -// for (int i = 0; i < this.taskList.size(); i++) { -// tasks.add(this.taskList.get(i)); -// } - String orderedList = getOutput(taskList); return orderedList; } diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index f30cce3784c..501f312da14 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -20,4 +20,4 @@ public Task(String description, String deadline) { public String toString() { return "Task: " + this.description + " " + deadline; } -} \ No newline at end of file +} From 59155699dba188036a20e392dd5194b7995dcafe Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 21 Mar 2022 16:46:44 +0800 Subject: [PATCH 040/140] Fix format of AboutUs.md --- docs/AboutUs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1d72b49dab9..5e25dd419ef 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,5 +1,6 @@ --- -ABOUT US +layout: page +title: About Us --- We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg). From 28c9d4b96d38a83ea92a12a283177ca0e80418b3 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 21 Mar 2022 16:52:53 +0800 Subject: [PATCH 041/140] Fix AboutUs.md --- docs/AboutUs.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 5e25dd419ef..953beefc1ad 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -17,6 +17,7 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/putaojuice.md)] * Role: Team Lead +* ### Low Weimin, Ian @@ -26,6 +27,7 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/castryl.md)] * Role: Documentation +* ### Ivor Chua @@ -35,6 +37,7 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/ivorcmx.md)] * Role: Testing +* ### Tan Yu Meng @@ -44,3 +47,4 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/yumengtan.md)] * Role: Code Quality +* From 233a0ff06b7f28f040a066916f826342a2e86f59 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 21 Mar 2022 17:10:37 +0800 Subject: [PATCH 042/140] Fix format for PPP --- docs/team/ivorcmx.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/team/ivorcmx.md b/docs/team/ivorcmx.md index ab8c8c701de..4f3b7387cea 100644 --- a/docs/team/ivorcmx.md +++ b/docs/team/ivorcmx.md @@ -1,5 +1,6 @@ --- -Ivor Chua's Project Portfolio Page +layout: page +title: Ivor's Project Portfolio Page --- ### Project: NUScheduler From 3b1e4b8747bd4f927338b4cdc00e979cae761b23 Mon Sep 17 00:00:00 2001 From: castryl Date: Mon, 21 Mar 2022 17:11:03 +0800 Subject: [PATCH 043/140] Add test coverage for view task command --- .../logic/commands/AddCommandTest.java | 8 +- .../logic/commands/AddTaskCommandTest.java | 8 +- .../logic/commands/DeleteTaskCommandTest.java | 8 +- .../logic/commands/FindTaskCommandTest.java | 8 +- .../logic/commands/ViewTaskCommandTest.java | 177 ++++++++++++++++++ 5 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index e68040431e0..8fd2b58ccfa 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -167,7 +167,13 @@ public void deleteTask(Integer taskNumber) { @Override public String findTask(String input) { - throw new AssertionError("This method should not be called."); } + throw new AssertionError("This method should not be called."); + } + + @Override + public String viewTask() { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 2b73283993e..2b23974c754 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -140,7 +140,13 @@ public void deleteTask(Integer taskNumber) { @Override public String findTask(String input) { - throw new AssertionError("This method should not be called."); } + throw new AssertionError("This method should not be called."); + } + + @Override + public String viewTask() { + throw new AssertionError("This method should not be called."); + } } private class ModelStubAcceptTask extends ModelStub { diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 2553f86ab2c..81de91885fd 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -113,6 +113,12 @@ public TaskList getTaskList() { @Override public String findTask(String input) { - throw new AssertionError("This method should not be called."); } + throw new AssertionError("This method should not be called."); + } + + @Override + public String viewTask() { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 2db1445d0ec..8a89cafa304 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -122,7 +122,13 @@ public TaskList getTaskList() { @Override public String findTask(String input) { - throw new AssertionError("This method should not be called."); } + throw new AssertionError("This method should not be called."); + } + + @Override + public String viewTask() { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java new file mode 100644 index 00000000000..599cbc3f6c2 --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -0,0 +1,177 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.logic.commands.ViewTaskCommand.MESSAGE_SUCCESS; +import static seedu.address.testutil.Assert.assertThrows; + +import java.nio.file.Path; +import java.util.function.Predicate; + +import org.junit.jupiter.api.Test; + +import javafx.collections.ObservableList; +import seedu.address.commons.core.GuiSettings; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; +import seedu.address.model.person.Person; +import seedu.address.model.task.Task; + +public class ViewTaskCommandTest { + + @Test + public void execute_taskListIsEmpty_throwsCommandException() { + ModelStubViewTask modelStubViewTask = new ModelStubViewTask(); + assertThrows(CommandException.class, () -> new ViewTaskCommand().execute(modelStubViewTask)); + } + + @Test + public void execute_nullModel_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new ViewTaskCommand().execute(null)); + } + + @Test + public void execute_taskListIsNotEmpty_viewSuccessful() throws CommandException { + ModelStubHasTask modelStubHasTask = new ModelStubHasTask(); + modelStubHasTask.addTask(new Task("description", "01/01/2022")); + String message = modelStubHasTask.viewTask(); + CommandResult commandResult = new ViewTaskCommand().execute(modelStubHasTask); + + assertEquals(MESSAGE_SUCCESS + "\n" + message, commandResult.getFeedbackToUser()); + } + + /** + * A default model stub that have all of the methods failing. + */ + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addTask(Task task) { + throw new AssertionError("This method should not be called."); + } + + @Override + public TaskList getTaskList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deleteTask(Integer taskNumber) { + throw new AssertionError("This method should not be called"); + } + + @Override + public String findTask(String input) { + throw new AssertionError("This method should not be called."); + } + + @Override + public String viewTask() { + throw new AssertionError("This method should not be called."); + } + } + + private class ModelStubViewTask extends ModelStub { + private TaskList taskList = new TaskList(); + + @Override + public TaskList getTaskList() { + return this.taskList; + } + + @Override + public String viewTask() { + return taskList.viewTask(); + } + } + + private class ModelStubHasTask extends ModelStub { + private TaskList taskList = new TaskList(); + + @Override + public void addTask(Task task) { + taskList.addTask(task); + } + + @Override + public TaskList getTaskList() { + return this.taskList; + } + + @Override + public String viewTask() { + return taskList.viewTask(); + } + } +} From 2c0d2cc643d4cc24d3741b974112dfbdf8d5abb5 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 21 Mar 2022 18:23:47 +0800 Subject: [PATCH 044/140] Update DG and PPP for v1.2 milestones --- docs/DeveloperGuide.md | 1 + docs/team/ivorcmx.md | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 514db55bd48..70b38e587ec 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -422,6 +422,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * **Private contact detail**: A contact detail that is not meant to be shared with others * **Task**: A task with descriptions and/or deadline * **Task list**: A task list of all the tasks +* **Task list ID**: ID assigned to corresponding task in the list * **Prefix**: A header (eg `d/`, `t/`) that is used to identify different clauses in user inputs. -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/team/ivorcmx.md b/docs/team/ivorcmx.md index 4f3b7387cea..ce9b0ecc1cc 100644 --- a/docs/team/ivorcmx.md +++ b/docs/team/ivorcmx.md @@ -9,26 +9,40 @@ NUScheduler is a desktop app for Year 1 Computing students to assist with more e Given below are my contributions to the project. -* **New Feature**: TBA -* **New Feature**: TBA - -* **Code contributed**: [RepoSense link]() TBA +* **New Feature**: Implemented `DeleteTask` command. + * What it does: Allow the user to delete a particular task based on its ID in the Tasklist + * Justification: Our target audience is year 1 computing students. It helps them to remove tasks that are not relevant anymore. + * **Classes created**: + * `DeleteTaskCommand` + * `DeleteTaskCommandParser` + * **Tests Written**: + * `DeleteTaskCommandTest` + * **Additional info**: + * Updated ParserUtil method of parseNumber to work with DeleteTaskCommand + +* **New Feature**: + * to be added soon + +* **Code contributed**: [RepoSense link (to be added soon)]() * **Project management**: - * TBA + * Managed release `v1.1`, `v1.2`. + * Participated in weekly project meetings and set up weekly milestones with the team. + * Reviewed pull requests. * **Enhancements to existing features**: - * TBA + * to be added soon * **Documentation**: * User Guide: - * TBA + * Added documentation for the feature `DeleteTask`. * Developer Guide: - * TBA + * Contribute to glossary in the developer guide. + * Added user story for Delete task feature. + * Added MSS for `DeleteTask`. * **Community**: - * TBA + * to be added soon * **Tools**: - * TBA - + * to be added soon From fa0ddec43b61ab80e6bdd11d308f1eee901bcdec Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 22 Mar 2022 14:29:04 +0800 Subject: [PATCH 045/140] Add more tests to improve coverage for DeleteTaskCommand & DeleteTaskCommandParser --- .../logic/commands/DeleteTaskCommand.java | 5 +- .../logic/commands/DeleteTaskCommandTest.java | 65 +++++++++++++++++++ .../parser/DeleteTaskCommandParserTest.java | 27 ++++++++ .../address/testutil/TypicalPersons.java | 3 + 4 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java diff --git a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java index 9475048aa36..936b82895dc 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java @@ -37,10 +37,7 @@ public DeleteTaskCommand(Integer taskNumber) { public CommandResult execute(Model model) throws CommandException { requireAllNonNull(model); - if (this.taskNumber.equals("")) { - // missing taskNumber, prompt the user with the format - throw new CommandException(MESSAGE_NO_INDEX + "\n" + MESSAGE_USAGE); - } else if (this.taskNumber <= 0 || this.taskNumber > model.getTaskList().size()) { + if (this.taskNumber <= 0 || this.taskNumber > model.getTaskList().size()) { throw new CommandException(MESSAGE_INDEX_OUT_OF_BOUNDS + "\n" + MESSAGE_USAGE); } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 2553f86ab2c..8d53c15442c 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -1,6 +1,13 @@ package seedu.address.logic.commands; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.nio.file.Path; import java.util.function.Predicate; @@ -9,19 +16,77 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.parser.DeleteTaskCommandParser; import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; +import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.model.task.Task; public class DeleteTaskCommandTest { + + private ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void constructor_ValidInputSuccess() throws Exception { + Integer taskNumberToBeDeleted = 1; + DeleteTaskCommand deleteTaskCommand = new DeleteTaskCommand(taskNumberToBeDeleted); + + model.addTask(new Task("test", "2022")); + + CommandResult commandResult = new DeleteTaskCommand(taskNumberToBeDeleted) + .execute(model); + + assertEquals(String.format(DeleteTaskCommand.MESSAGE_ARGUMENTS, taskNumberToBeDeleted), + commandResult.getFeedbackToUser()); + + } + + @Test + public void execute_OutofBoundsIndex_throwsCommandException() throws CommandException { + Integer outOfBoundIndex = model.getTaskList().size() + 1; + DeleteTaskCommand deleteTaskCommand = new DeleteTaskCommand(outOfBoundIndex); + String expectedMessage = DeleteTaskCommand.MESSAGE_INDEX_OUT_OF_BOUNDS + + "\n" + DeleteTaskCommand.MESSAGE_USAGE; + + assertCommandFailure(deleteTaskCommand, model, expectedMessage); + } + @Test public void constructor_nullDescription_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> new DeleteTaskCommand(null)); } + @Test + public void equals() { + DeleteTaskCommand deleteFirstTaskCommand = new DeleteTaskCommand(1); + DeleteTaskCommand deleteSecondTaskCommand = new DeleteTaskCommand(2); + + // same object -> returns true + assertTrue(deleteFirstTaskCommand.equals(deleteFirstTaskCommand)); + + // same values -> returns true + DeleteTaskCommand deleteFirstTaskCommandCopy = new DeleteTaskCommand(1); + assertTrue(deleteFirstTaskCommand.equals(deleteFirstTaskCommandCopy)); + + // different types -> returns false + assertFalse(deleteFirstTaskCommand.equals(1)); + + // null -> returns false + assertFalse(deleteFirstTaskCommand.equals(null)); + + // different person -> returns false + assertFalse(deleteFirstTaskCommand.equals(deleteSecondTaskCommand)); + } + + + /** * A default model stub that have all of the methods failing. */ diff --git a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java new file mode 100644 index 00000000000..f52bbade4b8 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java @@ -0,0 +1,27 @@ +package seedu.address.logic.parser; + + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.DeleteCommand; +import seedu.address.logic.commands.DeleteTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +public class DeleteTaskCommandParserTest { + + private DeleteTaskCommandParser parser = new DeleteTaskCommandParser(); + + @Test + public void parse_validArgs_returnsDeleteCommand() { + assertParseSuccess(parser, "1", new DeleteTaskCommand(1)); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } + +} diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index fec76fb7129..bdbec1f954c 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -16,6 +16,7 @@ import java.util.List; import seedu.address.model.AddressBook; +import seedu.address.model.TaskList; import seedu.address.model.person.Person; /** @@ -64,9 +65,11 @@ private TypicalPersons() {} // prevents instantiation */ public static AddressBook getTypicalAddressBook() { AddressBook ab = new AddressBook(); + TaskList taskList = new TaskList(); for (Person person : getTypicalPersons()) { ab.addPerson(person); } + return ab; } From f07eceaec82a0b7dd6a923aa608e73da26cc6cd7 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 22 Mar 2022 14:36:07 +0800 Subject: [PATCH 046/140] Fix checkStyle errors --- .../logic/commands/DeleteTaskCommandTest.java | 27 ++++++++----------- .../parser/DeleteTaskCommandParserTest.java | 5 ++-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 8d53c15442c..37d6f557041 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -5,8 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.nio.file.Path; @@ -16,10 +14,7 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.DeleteTaskCommandParser; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyAddressBook; @@ -34,26 +29,26 @@ public class DeleteTaskCommandTest { private ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); @Test - public void constructor_ValidInputSuccess() throws Exception { - Integer taskNumberToBeDeleted = 1; - DeleteTaskCommand deleteTaskCommand = new DeleteTaskCommand(taskNumberToBeDeleted); + public void constructor_validInputSuccess() throws Exception { + Integer taskNumberToBeDeleted = 1; + DeleteTaskCommand deleteTaskCommand = new DeleteTaskCommand(taskNumberToBeDeleted); - model.addTask(new Task("test", "2022")); + model.addTask(new Task("test", "2022")); - CommandResult commandResult = new DeleteTaskCommand(taskNumberToBeDeleted) - .execute(model); + CommandResult commandResult = new DeleteTaskCommand(taskNumberToBeDeleted) + .execute(model); - assertEquals(String.format(DeleteTaskCommand.MESSAGE_ARGUMENTS, taskNumberToBeDeleted), - commandResult.getFeedbackToUser()); + assertEquals(String.format(DeleteTaskCommand.MESSAGE_ARGUMENTS, taskNumberToBeDeleted), + commandResult.getFeedbackToUser()); } @Test - public void execute_OutofBoundsIndex_throwsCommandException() throws CommandException { + public void execute_outOfBoundsIndex_throwsCommandException() throws CommandException { Integer outOfBoundIndex = model.getTaskList().size() + 1; DeleteTaskCommand deleteTaskCommand = new DeleteTaskCommand(outOfBoundIndex); - String expectedMessage = DeleteTaskCommand.MESSAGE_INDEX_OUT_OF_BOUNDS + - "\n" + DeleteTaskCommand.MESSAGE_USAGE; + String expectedMessage = DeleteTaskCommand.MESSAGE_INDEX_OUT_OF_BOUNDS + + "\n" + DeleteTaskCommand.MESSAGE_USAGE; assertCommandFailure(deleteTaskCommand, model, expectedMessage); } diff --git a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java index f52bbade4b8..d21e2f79789 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java @@ -4,11 +4,12 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; + import org.junit.jupiter.api.Test; + import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DeleteTaskCommand; -import seedu.address.logic.parser.exceptions.ParseException; + public class DeleteTaskCommandParserTest { From c33abc974b5de474815bee0dac2e2bf99ad5106c Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 22 Mar 2022 20:49:22 +0800 Subject: [PATCH 047/140] Remove unnecessary line of code --- src/test/java/seedu/address/testutil/TypicalPersons.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index bdbec1f954c..e70687a6971 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -65,7 +65,6 @@ private TypicalPersons() {} // prevents instantiation */ public static AddressBook getTypicalAddressBook() { AddressBook ab = new AddressBook(); - TaskList taskList = new TaskList(); for (Person person : getTypicalPersons()) { ab.addPerson(person); } From ae8e832715e16629f85869a4cff7edfba89a01ac Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 22 Mar 2022 20:52:11 +0800 Subject: [PATCH 048/140] Add additional invalid symbols test to DeleteTaskCommandParserTest --- .../address/logic/parser/DeleteTaskCommandParserTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java index d21e2f79789..ebcece3d874 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java @@ -25,4 +25,9 @@ public void parse_invalidArgs_throwsParseException() { assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } + @Test + public void parse_invalidSymbols_throwsParseException() { + assertParseFailure(parser, "$%^%$^%#$", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } + } From 3ef78c8dbf33889e0d3c8ceafdb39e5684608156 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 22 Mar 2022 20:54:59 +0800 Subject: [PATCH 049/140] Fix checkstyle errors --- .../address/logic/parser/DeleteTaskCommandParserTest.java | 6 ++++-- src/test/java/seedu/address/testutil/TypicalPersons.java | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java index ebcece3d874..11257bd7ef6 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java @@ -22,12 +22,14 @@ public void parse_validArgs_returnsDeleteCommand() { @Test public void parse_invalidArgs_throwsParseException() { - assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "a", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } @Test public void parse_invalidSymbols_throwsParseException() { - assertParseFailure(parser, "$%^%$^%#$", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + assertParseFailure(parser, "$%^%$^%#$", + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } } diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index e70687a6971..2937d1066ef 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -16,7 +16,6 @@ import java.util.List; import seedu.address.model.AddressBook; -import seedu.address.model.TaskList; import seedu.address.model.person.Person; /** From 50fefd4581e2669b381913e4a4d73387f5e53215 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 23 Mar 2022 19:12:20 +0800 Subject: [PATCH 050/140] Add tests to improve coverage --- .../logic/parser/FindTaskCommandParser.java | 6 ++ .../logic/commands/FindTaskCommandTest.java | 58 +++++++++++++++++-- .../parser/FindTaskCommandParserTest.java | 25 ++++++++ 3 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 src/test/java/seedu/address/logic/parser/FindTaskCommandParserTest.java diff --git a/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java index 6703cfd11a3..1b20cdd9ecb 100644 --- a/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindTaskCommandParser.java @@ -1,6 +1,7 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import seedu.address.logic.commands.FindTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -14,6 +15,11 @@ public class FindTaskCommandParser implements Parser { */ public FindTaskCommand parse(String args) throws ParseException { requireNonNull(args); + String trimmedArgs = args.trim(); + if (trimmedArgs.isEmpty()) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTaskCommand.MESSAGE_USAGE)); + } return new FindTaskCommand(args); } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 8a89cafa304..242b40b58d3 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -1,6 +1,10 @@ package seedu.address.logic.commands; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.nio.file.Path; import java.util.function.Predicate; @@ -9,10 +13,13 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; +import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; +import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.model.task.Task; @@ -21,16 +28,59 @@ */ public class FindTaskCommandTest { + private final ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + + @Test + public void constructor_nullInput_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> new FindTaskCommand(null)); + } + @Test - public void constructor_nullDescription_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new AddTaskCommand(null)); + public void execute_validInputSuccess() throws CommandException { + String testInputSuccess = "test"; + FindTaskCommand findTaskCommand = new FindTaskCommand(testInputSuccess); + model.addTask(new Task("test", "2022")); + CommandResult commandResult = findTaskCommand + .execute(model); + String taskSuccess = model.findTask(testInputSuccess); + assertEquals(String.format(FindTaskCommand.MESSAGE_ARGUMENTS, taskSuccess), + commandResult.getFeedbackToUser()); } @Test - public void constructor_nullDescriptionAndDeadline_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new AddTaskCommand(null, null)); + public void execute_validInput_noTaskFound() { + String testInputUnsuccessful = "fail"; + FindTaskCommand findTaskCommand = new FindTaskCommand(testInputUnsuccessful); + model.addTask(new Task("test", "2022")); + String expectedMessage = FindTaskCommand.MESSAGE_NO_MATCHING_TASK; + assertThrows(CommandException.class, expectedMessage, () -> findTaskCommand.execute(model)); } + @Test + public void equals() { + String firstTest = "test1"; + String secondTest = "test2"; + FindTaskCommand findFirstTaskCommand = new FindTaskCommand(firstTest); + FindTaskCommand findSecondTaskCommand = new FindTaskCommand(secondTest); + + // same object -> returns true + assertTrue(findFirstTaskCommand.equals(findFirstTaskCommand)); + + // same values -> returns true + FindTaskCommand findFirstTaskCommandCopy = new FindTaskCommand(firstTest); + assertTrue(findFirstTaskCommand.equals(findFirstTaskCommandCopy)); + + // different types -> returns false + assertFalse(findFirstTaskCommand.equals(firstTest)); + + // null -> returns false + assertFalse(findFirstTaskCommand.equals(null)); + + // different person -> returns false + assertFalse(findFirstTaskCommand.equals(findSecondTaskCommand)); + } + + /** * A default model stub that have all the methods failing. */ diff --git a/src/test/java/seedu/address/logic/parser/FindTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindTaskCommandParserTest.java new file mode 100644 index 00000000000..1fd0128e988 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/FindTaskCommandParserTest.java @@ -0,0 +1,25 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.commands.FindTaskCommand; + +public class FindTaskCommandParserTest { + + private final FindTaskCommandParser parser = new FindTaskCommandParser(); + + @Test + public void parse_invalidArgs_throwsParseException() { + assertParseFailure(parser, "", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTaskCommand.MESSAGE_USAGE)); + } + + @Test + public void parse_validArgs_returnsFindCommand() { + assertParseSuccess(parser, "test", new FindTaskCommand("test")); + } + +} From 89b2430e9002b335b23ef40c74bb559d8e34e698 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Thu, 24 Mar 2022 02:02:35 +0800 Subject: [PATCH 051/140] Update DG and UG - Add proposed feature in DG - Add sequence diagram in DG - Add activity diagram in DG - Correct UG mistake on add task command format --- docs/DeveloperGuide.md | 27 ++++++++++++++++++ docs/UserGuide.md | 4 +-- docs/images/AddTaskCommandActivityDiagram.png | Bin 0 -> 32327 bytes docs/images/AddTaskCommandSequenceDiagram.png | Bin 0 -> 47908 bytes 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 docs/images/AddTaskCommandActivityDiagram.png create mode 100644 docs/images/AddTaskCommandSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 70b38e587ec..d99459bb21a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -239,6 +239,33 @@ _{more aspects and alternatives to be added}_ _{Explain here how the data archiving feature will be implemented}_ +### \[Proposed\] Add Task Feature (Yu An) +#### Proposed Implementation +The proposed add task feature is facilitated by `AddTaskCommand`. It extends `Command` and make use of a new model `TaskList` and `Task`. +The `TaskList` model consists of an `ArrayList` to store the `Task`. The `AddTaskCommand` also has a `AddTaskCommandParser` +to do the logical parsing of user's input. Additionally, this feature implements the following operations: + +* `AddTaskCommand#execute()` — Executes the command. +* `AddTaskCommandParser#parse()` — Make sense of the user's input and returns an `AddTaskCommand` object. +* `TaskList#addTask()` — Add a new task to the task list if user's input is valid. + +The `TaskList#addTask()` is exposed in the `Model` interface as `Model#addTask()`. + +Given below is an example usage scenario and how the add task feature works. + +The following activity diagram shows the workflow of add task operation: + +The user will type in the command `addt d/DESCRIPTION [t/DEADLINE (dd/mm/yyyy)]` with the deadline being optional field. +If a valid format is detected, the system will create a new task, add it to the task list and prompt the user that a +task has been successfully added. + +![AddTaskCommandActivityDiagram](images/AddTaskCommandActivityDiagram.png) + +The following sequence diagram shows how the add task operation work assuming no exception is thrown: + +![AddTaskCommandSequenceDiagram](images/AddTaskCommandSequenceDiagram.png) + +_{more aspects and alternatives to be added}_ -------------------------------------------------------------------------------------------------------------------- ## **Documentation, logging, testing, configuration, dev-ops** diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a887aa717ac..bb5f37372ec 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -74,9 +74,9 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona Adds a task to the task list. -Format: `addt d/DESCRIPTION [t/DEADLINE]` +Format: `addt d/DESCRIPTION [t/DEADLINE (dd/mm/yyyy)]` -Example: `addt d/Buy groceries [t/2022 02 22 5pm]` +Example: `addt d/Buy groceries [t/01/01/2022]` ### Feature - Delete a task: `delt ` diff --git a/docs/images/AddTaskCommandActivityDiagram.png b/docs/images/AddTaskCommandActivityDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..480182ba400bcbad45c14bf65b519a4f2694818f GIT binary patch literal 32327 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 literal 0 HcmV?d00001 diff --git a/docs/images/AddTaskCommandSequenceDiagram.png b/docs/images/AddTaskCommandSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..247ce1b8fa81952d3ff19f1e655ca7f64e04e218 GIT binary patch literal 47908 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 Date: Thu, 24 Mar 2022 16:55:57 +0800 Subject: [PATCH 052/140] Storage for TaskList This commit adds the feature of saving the task list to tasklist.json and reading saved data from it when the user relaunch the application. - Add ReadOnlyTaskList - Add JsonAdaptedTask - Add JsonSerializableTaskList - Add JsonTaskListStorage - Add TaskListStorage --- src/main/java/seedu/address/MainApp.java | 35 ++++++---- .../seedu/address/logic/LogicManager.java | 2 + src/main/java/seedu/address/model/Model.java | 4 ++ .../seedu/address/model/ModelManager.java | 21 +++++- .../seedu/address/model/ReadOnlyTaskList.java | 16 +++++ .../java/seedu/address/model/TaskList.java | 32 ++++++++- .../java/seedu/address/model/UserPrefs.java | 10 +++ .../java/seedu/address/model/task/Task.java | 8 +++ .../address/model/util/SampleDataUtil.java | 16 +++++ .../address/storage/JsonAdaptedTask.java | 48 ++++++++++++++ .../storage/JsonSerializableTaskList.java | 41 ++++++++++++ .../address/storage/JsonTaskListStorage.java | 65 +++++++++++++++++++ .../java/seedu/address/storage/Storage.java | 11 +++- .../seedu/address/storage/StorageManager.java | 32 ++++++++- .../address/storage/TaskListStorage.java | 24 +++++++ 15 files changed, 343 insertions(+), 22 deletions(-) create mode 100644 src/main/java/seedu/address/model/ReadOnlyTaskList.java create mode 100644 src/main/java/seedu/address/storage/JsonAdaptedTask.java create mode 100644 src/main/java/seedu/address/storage/JsonSerializableTaskList.java create mode 100644 src/main/java/seedu/address/storage/JsonTaskListStorage.java create mode 100644 src/main/java/seedu/address/storage/TaskListStorage.java diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 4133aaa0151..b64e0a6f91e 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -15,19 +15,9 @@ import seedu.address.commons.util.StringUtil; import seedu.address.logic.Logic; import seedu.address.logic.LogicManager; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; +import seedu.address.model.*; import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.AddressBookStorage; -import seedu.address.storage.JsonAddressBookStorage; -import seedu.address.storage.JsonUserPrefsStorage; -import seedu.address.storage.Storage; -import seedu.address.storage.StorageManager; -import seedu.address.storage.UserPrefsStorage; +import seedu.address.storage.*; import seedu.address.ui.Ui; import seedu.address.ui.UiManager; @@ -57,7 +47,8 @@ public void init() throws Exception { UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); UserPrefs userPrefs = initPrefs(userPrefsStorage); AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath()); - storage = new StorageManager(addressBookStorage, userPrefsStorage); + TaskListStorage taskListStorage = new JsonTaskListStorage(userPrefs.getTaskListFilePath()); + storage = new StorageManager(addressBookStorage, userPrefsStorage, taskListStorage); initLogging(config); @@ -90,7 +81,23 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) { initialData = new AddressBook(); } - return new ModelManager(initialData, userPrefs); + Optional taskListOptional; + ReadOnlyTaskList initialDataTaskList; + try { + taskListOptional = storage.readTaskList(); + if (!taskListOptional.isPresent()) { + logger.info("Data file not found. Will be starting with an empty TaskList"); + } + initialDataTaskList = taskListOptional.orElseGet(SampleDataUtil::getSampleTaskList); + } catch (DataConversionException e) { + logger.warning("Data file not in the correct format. Will be starting with an empty TaskList"); + initialDataTaskList = new TaskList(); + } catch (IOException e) { + logger.warning("Problem while reading from the file. Will be starting with an empty TaskList"); + initialDataTaskList = new TaskList(); + } + + return new ModelManager(initialData, userPrefs, initialDataTaskList); } private void initLogging(Config config) { diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9d9c6d15bdc..d19ea63cf72 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -46,6 +46,8 @@ public CommandResult execute(String commandText) throws CommandException, ParseE commandResult = command.execute(model); try { + //TODO saveTaskList + storage.saveTaskList(model.getReadOnlyTaskList()); storage.saveAddressBook(model.getAddressBook()); } catch (IOException ioe) { throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 5da537d9164..682e009e722 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -99,4 +99,8 @@ public interface Model { String findTask(String input); String viewTask(); + + Path getTaskListFilePath(); + void setTaskListFilePath(Path taskListFilePath); + ReadOnlyTaskList getReadOnlyTaskList(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index ffe4ef18c5e..65a55b69a23 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -29,7 +29,7 @@ public class ModelManager implements Model { /** * Initializes a ModelManager with the given addressBook and userPrefs. */ - public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) { + public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs, ReadOnlyTaskList taskList) { requireAllNonNull(addressBook, userPrefs); logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); @@ -38,11 +38,11 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); - this.taskList = new TaskList(); + this.taskList = new TaskList(taskList); } public ModelManager() { - this(new AddressBook(), new UserPrefs()); + this(new AddressBook(), new UserPrefs(), new TaskList()); } //=========== UserPrefs ================================================================================== @@ -80,6 +80,17 @@ public void setAddressBookFilePath(Path addressBookFilePath) { userPrefs.setAddressBookFilePath(addressBookFilePath); } + @Override + public Path getTaskListFilePath() { + return userPrefs.getTaskListFilePath(); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + requireNonNull(taskListFilePath); + userPrefs.setTaskListFilePath(taskListFilePath); + } + //=========== AddressBook ================================================================================ @Override @@ -164,6 +175,10 @@ public TaskList getTaskList() { return this.taskList; } + public ReadOnlyTaskList getReadOnlyTaskList() { + return this.taskList; + } + //=========== Delete Task ================================================================================== @Override diff --git a/src/main/java/seedu/address/model/ReadOnlyTaskList.java b/src/main/java/seedu/address/model/ReadOnlyTaskList.java new file mode 100644 index 00000000000..ff0df71db4e --- /dev/null +++ b/src/main/java/seedu/address/model/ReadOnlyTaskList.java @@ -0,0 +1,16 @@ +package seedu.address.model; + +import javafx.collections.ObservableList; +import seedu.address.model.task.Task; + +/** + * Unmodifiable view of a task list + */ +public interface ReadOnlyTaskList { + + /** + * Returns an unmodifiable view of the task list. + */ + ObservableList getObservableTaskList(); + +} diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 7b5309f1320..ed4b7c7bbd9 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -3,14 +3,34 @@ import static java.util.Objects.requireNonNull; import java.util.ArrayList; +import java.util.List; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import seedu.address.model.task.Task; -public class TaskList { +public class TaskList implements ReadOnlyTaskList { private final ArrayList taskList; - public TaskList() { - this.taskList = new ArrayList<>(); + { + taskList = new ArrayList<>(); + } + + public TaskList() {} + + public TaskList(ReadOnlyTaskList toBeCopied) { + this(); + resetData(toBeCopied); + } + + public void resetData(ReadOnlyTaskList newData) { + requireNonNull(newData); + + setTaskList(newData.getObservableTaskList()); + } + + public void setTaskList(List tasks) { + this.taskList.addAll(tasks); } /** @@ -86,6 +106,12 @@ private String getOutput(ArrayList list) { } return sb.toString(); } + + @Override + public ObservableList getObservableTaskList() { + ObservableList taskObservableList = FXCollections.observableArrayList(taskList); + return taskObservableList; + } } diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 25a5fd6eab9..3336e1d3879 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/seedu/address/model/UserPrefs.java @@ -15,6 +15,7 @@ public class UserPrefs implements ReadOnlyUserPrefs { private GuiSettings guiSettings = new GuiSettings(); private Path addressBookFilePath = Paths.get("data" , "addressbook.json"); + private Path taskListFilePath = Paths.get("data" , "tasklist.json"); /** * Creates a {@code UserPrefs} with default values. @@ -56,6 +57,15 @@ public void setAddressBookFilePath(Path addressBookFilePath) { this.addressBookFilePath = addressBookFilePath; } + public Path getTaskListFilePath() { + return taskListFilePath; + } + + public void setTaskListFilePath(Path taskListFilePath) { + requireNonNull(taskListFilePath); + this.taskListFilePath = taskListFilePath; + } + @Override public boolean equals(Object other) { if (other == this) { diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 501f312da14..c09616d51a3 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -16,6 +16,14 @@ public Task(String description, String deadline) { this.deadline = deadline; } + public String getDescription() { + return this.description; + } + + public String getDeadline() { + return this.deadline; + } + @Override public String toString() { return "Task: " + this.description + " " + deadline; diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 1806da4facf..543ff498d40 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -6,12 +6,15 @@ import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.TaskList; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; +import seedu.address.model.task.Task; /** * Contains utility methods for populating {@code AddressBook} with sample data. @@ -57,4 +60,17 @@ public static Set getTagSet(String... strings) { .collect(Collectors.toSet()); } + public static Task[] getSampleTask() { + return new Task[] { + new Task("dummy", "01/01/2022") + }; + } + + public static ReadOnlyTaskList getSampleTaskList() { + TaskList sampleTaskList = new TaskList(); + for (Task sampleTask : getSampleTask()) { + sampleTaskList.addTask(sampleTask); + } + return sampleTaskList; + } } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTask.java b/src/main/java/seedu/address/storage/JsonAdaptedTask.java new file mode 100644 index 00000000000..caa9f9d410c --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonAdaptedTask.java @@ -0,0 +1,48 @@ +package seedu.address.storage; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.task.Task; + +public class JsonAdaptedTask { + + public static final String MISSING_FIELD_MESSAGE_FORMAT = "Task's %s field is missing!"; + + private final String description; + private final String deadline; + + @JsonCreator + public JsonAdaptedTask(@JsonProperty("description") String description, @JsonProperty("deadline") String deadline) { + this.description = description; + this.deadline = deadline; + } + + public JsonAdaptedTask(Task source) { + description = source.getDescription(); + deadline = source.getDeadline(); + } + + public Task toModelType() throws IllegalValueException { + if (description == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, "description")); + } + + final String modelDescription = description; + + if (deadline == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, "deadline")); + } + + final String modelDeadline = deadline; + + return new Task(modelDescription, modelDeadline); + } +} diff --git a/src/main/java/seedu/address/storage/JsonSerializableTaskList.java b/src/main/java/seedu/address/storage/JsonSerializableTaskList.java new file mode 100644 index 00000000000..8f225f98a06 --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonSerializableTaskList.java @@ -0,0 +1,41 @@ +package seedu.address.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.model.TaskList; +import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.task.Task; + +/** + * An Immutable TaskList that is serializable to JSON format. + */ +@JsonRootName(value = "tasklist") +public class JsonSerializableTaskList { + + private final List tasks = new ArrayList<>(); + + @JsonCreator + public JsonSerializableTaskList(@JsonProperty("tasks") List tasks) { + this.tasks.addAll(tasks); + } + + public JsonSerializableTaskList(ReadOnlyTaskList source) { + tasks.addAll(source.getObservableTaskList().stream().map(JsonAdaptedTask::new).collect(Collectors.toList())); + } + + public TaskList toModelType() throws IllegalValueException { + TaskList taskList = new TaskList(); + for (JsonAdaptedTask jsonAdaptedTask : tasks) { + Task task = jsonAdaptedTask.toModelType(); + taskList.addTask(task); + } + return taskList; + } +} diff --git a/src/main/java/seedu/address/storage/JsonTaskListStorage.java b/src/main/java/seedu/address/storage/JsonTaskListStorage.java new file mode 100644 index 00000000000..d57d4272ce4 --- /dev/null +++ b/src/main/java/seedu/address/storage/JsonTaskListStorage.java @@ -0,0 +1,65 @@ +package seedu.address.storage; + +import static java.util.Objects.requireNonNull; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; +import java.util.logging.Logger; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.commons.util.FileUtil; +import seedu.address.commons.util.JsonUtil; +import seedu.address.model.ReadOnlyTaskList; + +public class JsonTaskListStorage implements TaskListStorage { + + private static final Logger logger = LogsCenter.getLogger(JsonTaskListStorage.class); + + private Path filePath; + + public JsonTaskListStorage(Path filePath) { + this.filePath = filePath; + } + + public Path getTaskListFilePath() { + return filePath; + } + + @Override + public Optional readTaskList() throws DataConversionException, IOException { + return readTaskList(filePath); + } + + public Optional readTaskList(Path filePath) throws DataConversionException, IOException { + requireNonNull(filePath); + + Optional jsonTaskList = JsonUtil.readJsonFile( + filePath, JsonSerializableTaskList.class); + if (!jsonTaskList.isPresent()) { + return Optional.empty(); + } + + try { + return Optional.of(jsonTaskList.get().toModelType()); + } catch (IllegalValueException ive) { + logger.info("Illegal values found in " + filePath + ": " + ive.getMessage()); + throw new DataConversionException(ive); + } + } + + @Override + public void saveTaskList(ReadOnlyTaskList taskList) throws IOException { + saveTaskList(taskList, filePath); + } + + public void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException { + requireNonNull(taskList); + requireNonNull(filePath); + + FileUtil.createIfMissing(filePath); + JsonUtil.saveJsonFile(new JsonSerializableTaskList(taskList), filePath); + } +} diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java index beda8bd9f11..bb2fc37cb2a 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/seedu/address/storage/Storage.java @@ -6,13 +6,14 @@ import seedu.address.commons.exceptions.DataConversionException; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.UserPrefs; /** * API of the Storage component */ -public interface Storage extends AddressBookStorage, UserPrefsStorage { +public interface Storage extends AddressBookStorage, UserPrefsStorage, TaskListStorage { @Override Optional readUserPrefs() throws DataConversionException, IOException; @@ -29,4 +30,12 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage { @Override void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; + @Override + Path getTaskListFilePath(); + + @Override + Optional readTaskList() throws DataConversionException, IOException; + + @Override + void saveTaskList(ReadOnlyTaskList taskList) throws IOException; } diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index 6cfa0162164..55947b87934 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -8,6 +8,7 @@ import seedu.address.commons.core.LogsCenter; import seedu.address.commons.exceptions.DataConversionException; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.UserPrefs; @@ -19,13 +20,15 @@ public class StorageManager implements Storage { private static final Logger logger = LogsCenter.getLogger(StorageManager.class); private AddressBookStorage addressBookStorage; private UserPrefsStorage userPrefsStorage; + private TaskListStorage taskListStorage; /** * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}. */ - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) { + public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage, TaskListStorage taskListStorage) { this.addressBookStorage = addressBookStorage; this.userPrefsStorage = userPrefsStorage; + this.taskListStorage = taskListStorage; } // ================ UserPrefs methods ============================== @@ -75,4 +78,31 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) thro addressBookStorage.saveAddressBook(addressBook, filePath); } + // ================ TaskList methods ============================== + @Override + public Path getTaskListFilePath() { + return taskListStorage.getTaskListFilePath(); + } + + @Override + public Optional readTaskList() throws DataConversionException, IOException { + return readTaskList(taskListStorage.getTaskListFilePath()); + } + + @Override + public Optional readTaskList(Path filePath) throws DataConversionException, IOException { + logger.fine("Attempting to read data from file: " + filePath); + return taskListStorage.readTaskList(filePath); + } + + @Override + public void saveTaskList(ReadOnlyTaskList taskList) throws IOException { + saveTaskList(taskList, taskListStorage.getTaskListFilePath()); + } + + @Override + public void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException{ + logger.fine("Attempting to write to data file: " + filePath); + taskListStorage.saveTaskList(taskList, filePath); + } } diff --git a/src/main/java/seedu/address/storage/TaskListStorage.java b/src/main/java/seedu/address/storage/TaskListStorage.java new file mode 100644 index 00000000000..84fa9043b9f --- /dev/null +++ b/src/main/java/seedu/address/storage/TaskListStorage.java @@ -0,0 +1,24 @@ +package seedu.address.storage; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.model.ReadOnlyTaskList; + +public interface TaskListStorage { + + /** + * Returns the file path of the data file. + */ + Path getTaskListFilePath(); + + Optional readTaskList() throws DataConversionException, IOException; + + Optional readTaskList(Path filePath) throws DataConversionException, IOException; + + void saveTaskList(ReadOnlyTaskList taskList) throws IOException; + + void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException; +} From 4a6ab0048c9f3678472740e5c1c3c97749f8d92d Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Thu, 24 Mar 2022 17:04:56 +0800 Subject: [PATCH 053/140] Trial jar v1.3 release --- src/main/java/seedu/address/MainApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 4133aaa0151..8c81ba20092 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -36,7 +36,7 @@ */ public class MainApp extends Application { - public static final Version VERSION = new Version(0, 2, 0, true); + public static final Version VERSION = new Version(1, 3, 0, true); private static final Logger logger = LogsCenter.getLogger(MainApp.class); From e2886ec1c00ce7ff59baf3157199807b15114be3 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Thu, 24 Mar 2022 17:10:57 +0800 Subject: [PATCH 054/140] Enable assertion --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index be2d2905dde..9b493f90558 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,10 @@ checkstyle { toolVersion = '8.29' } +run { + enableAssertions = true +} + test { useJUnitPlatform() finalizedBy jacocoTestReport From 68dc7f268f9b8e0a2aa81a4881d5722314eeb5eb Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 24 Mar 2022 20:05:58 +0800 Subject: [PATCH 055/140] Update DG and PPP --- docs/DeveloperGuide.md | 25 ++++++++ docs/diagrams/FindTaskActivityDiagram.puml | 33 +++++++++++ docs/diagrams/FindTaskSequenceDiagram.puml | 63 +++++++++++++++++++++ docs/images/FindTaskActivityDiagram.png | Bin 0 -> 23044 bytes docs/images/FindTaskSequenceDiagram.png | Bin 0 -> 26904 bytes docs/team/yumengtan.md | 5 +- 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 docs/diagrams/FindTaskActivityDiagram.puml create mode 100644 docs/diagrams/FindTaskSequenceDiagram.puml create mode 100644 docs/images/FindTaskActivityDiagram.png create mode 100644 docs/images/FindTaskSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d99459bb21a..bd5aceee9de 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -265,6 +265,31 @@ The following sequence diagram shows how the add task operation work assuming no ![AddTaskCommandSequenceDiagram](images/AddTaskCommandSequenceDiagram.png) + +### \[Proposed\] Find Task Feature (Yu Meng) +#### Proposed Implementation +The proposed find task feature is facilitated by `FindTaskCommand`. It extends `Command` and makes use of the `TaskList` model +and `Task`. The `TaskList` Model is used to retrieve the `Tasks` that have been stored. The `FindTaskCommand` also has a +`FindTaskCommandParser` to do the logical parsing of the user's input. It uses regex to ignore case sensitivity of user's input. +These are the operations that the feature implements: +* `FindTaskCommand#execute()` : Executes the command. +* `FindTaskCommandParser#parse()` : Parses the user input and returns a `FindTaskCommand` Object. +* `TaskList#findTask()` : Finds and returns tasks matching keyword from user input (ignores case sensitivity) + +Given Below is an example usage scenario and how the find task feature works. + +The following activity diagram shows the workflow of add task operation: + +The user will type in the command `findt KEYWORD`. If the user inputs a valid format, the system will retrieve matching +tasks from the TaskList. If there is one or more matching Tasks, the system will prompt the user with the matching Tasks. + +![FindTaskCommandActivityDiagram](images/FindTaskActivityDiagram.png) + +The following sequence diagram shows how the add task operation work assuming no exception is thrown: + +![FindTaskCommandSequenceDiagram](images/FindTaskSequenceDiagram.png) + + _{more aspects and alternatives to be added}_ -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/diagrams/FindTaskActivityDiagram.puml b/docs/diagrams/FindTaskActivityDiagram.puml new file mode 100644 index 00000000000..2a04ca217ae --- /dev/null +++ b/docs/diagrams/FindTaskActivityDiagram.puml @@ -0,0 +1,33 @@ +@startuml + +skinparam backgroundColor #F6E3D4 +skinparam classFontSize 12 +skinparam maxMessageSize 20 +skinparam wrapWidth 160 +skinparam activity { + StartColor Chocolate + BackGroundColor OldLace + BorderColor Black + ArrowColor Sienna + EndColor Chocolate +} + + start + :User type in the find task command; + 'Since the beta syntax does not support placing the condition outside the + 'diamond we place it as the true branch instead. + if () then ([Valid format and/or input]) + -Retrieve matching tasks from TaskList; + if () then ([Contain one or more matching tasks]) + -Prompt user with matching tasks in Tasklist + else ([else]) + -Prompt user no matching tasks found + endif + + else ([else]) + -"Prompt user with the command's format" + + endif + stop + +@enduml \ No newline at end of file diff --git a/docs/diagrams/FindTaskSequenceDiagram.puml b/docs/diagrams/FindTaskSequenceDiagram.puml new file mode 100644 index 00000000000..bbc49ced057 --- /dev/null +++ b/docs/diagrams/FindTaskSequenceDiagram.puml @@ -0,0 +1,63 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":FindTaskCommandParser" as FindTaskCommandParser LOGIC_COLOR +participant "f:FindTaskCommand" as FindTaskCommand LOGIC_COLOR +participant "r:CommandResult" as CommandResult LOGIC_COLOR +end box + +box TaskList MODEL_COLOR_T1 +participant "taskList:TaskList" as Model MODEL_COLOR +end box + +[-> LogicManager : execute("findt demo") +activate LogicManager + +LogicManager -> AddressBookParser : parseCommand("findt demo") +activate AddressBookParser + +create FindTaskCommandParser +AddressBookParser -> FindTaskCommandParser +activate FindTaskCommandParser + +create FindTaskCommand +FindTaskCommandParser -> FindTaskCommand +activate FindTaskCommand + +FindTaskCommandParser --> AddressBookParser +deactivate FindTaskCommand + +FindTaskCommand --> FindTaskCommandParser +deactivate FindTaskCommandParser + +FindTaskCommandParser -[hidden]-> AddressBookParser +destroy FindTaskCommandParser + +AddressBookParser --> LogicManager +deactivate FindTaskCommandParser + +LogicManager -> FindTaskCommand: execute(model) +activate FindTaskCommand + +FindTaskCommand -> Model : findTask(demo) +activate Model + +Model --> FindTaskCommand +deactivate Model + +create CommandResult +FindTaskCommand -> CommandResult +activate CommandResult + +CommandResult --> FindTaskCommand +deactivate CommandResult + +FindTaskCommand --> LogicManager : result +deactivate FindTaskCommand + +[<--LogicManager +deactivate LogicManager +@enduml \ No newline at end of file diff --git a/docs/images/FindTaskActivityDiagram.png b/docs/images/FindTaskActivityDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2369f06e3fc700eea0ab7cfc238a5dc4414323e2 GIT binary patch literal 23044 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 literal 0 HcmV?d00001 diff --git a/docs/team/yumengtan.md b/docs/team/yumengtan.md index 8c94c0f81f6..5e3fd037808 100644 --- a/docs/team/yumengtan.md +++ b/docs/team/yumengtan.md @@ -26,7 +26,7 @@ Given below are my contributions to the project. * **Code contributed**: [RepoSense link (to be added soon)]() * **Project management**: - * Managed release `v1.1`, `v1.2`. + * Managed release `v1.1`, `v1.2`, `v1.3`. * Participated in weekly project meetings and set up weekly milestones with the team. * Reviewed pull requests. @@ -40,6 +40,9 @@ Given below are my contributions to the project. * Contribute to glossary in the developer guide. * Added user story for find task feature. * Added MSS for `FindTask`. + * Diagrams + * Added Sequence Diagram for `FindTask` + * Added Activity Diagram for `FindTask` * **Community**: * to be added soon From e283e4b353c0b6ab287f9acbde969f50eeee01d7 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Thu, 24 Mar 2022 21:59:56 +0800 Subject: [PATCH 056/140] Add proposed feature in DG Add sequence diagram in DG Add activity diagram in DG Fixes #43 --- docs/DeveloperGuide.md | 28 +++++++++ docs/diagrams/DeleteTaskActivityDiagram.puml | 18 ++++++ docs/diagrams/DeleteTaskSequenceDiagram.puml | 63 +++++++++++++++++++ docs/images/DeleteTaskActivityDiagram.png | Bin 0 -> 21510 bytes docs/images/DeleteTaskSequenceDiagram.png | Bin 0 -> 32494 bytes 5 files changed, 109 insertions(+) create mode 100644 docs/diagrams/DeleteTaskActivityDiagram.puml create mode 100644 docs/diagrams/DeleteTaskSequenceDiagram.puml create mode 100644 docs/images/DeleteTaskActivityDiagram.png create mode 100644 docs/images/DeleteTaskSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d99459bb21a..55cefb375ce 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -265,6 +265,34 @@ The following sequence diagram shows how the add task operation work assuming no ![AddTaskCommandSequenceDiagram](images/AddTaskCommandSequenceDiagram.png) +_{more aspects and alternatives to be added}_ + +### \[Proposed\] Add Delete Task Feature (Ivor) +#### Proposed Implementation +The proposed delete task feature is facilitated by `DeleteTaskCommand`. It extends `Command` and make use of a new model `TaskList` and `Task`. +The `TaskList` model consists of an `ArrayList` to store the `Task`. The `DeketeTaskCommand` also has a `DeleteTaskCommandParser` +to do the logical parsing of user's input. Additionally, this feature implements the following operations: + +* `DeleteTaskCommand#execute()` — Executes the command. +* `DeleteTaskCommandParser#parse()` — Make sense of the user's input and returns an `DeleteTaskCommand` object. +* `TaskList#DeleteTask()` — Delete an existing task in the task list if user's input is valid. + +The `TaskList#deleteTask()` is exposed in the `Model` interface as `Model#deleteTask()`. + +Given below is an example usage scenario and how the delete task feature works. + +The following activity diagram shows the workflow of delete task operation: + +The user will type in the command `delt `. +If a valid format is detected, the system will remove the corresponding task with the integer ID, and prompt the user that a +task has been successfully deleted. + +![DeleteTaskCommandActivityDiagram](images/DeleteTaskActivityDiagram.png) + +The following sequence diagram shows how the delete task operation work assuming no exception is thrown: + +![DeleteTaskCommandSequenceDiagram](images/DeleteTaskSequenceDiagram.png) + _{more aspects and alternatives to be added}_ -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/diagrams/DeleteTaskActivityDiagram.puml b/docs/diagrams/DeleteTaskActivityDiagram.puml new file mode 100644 index 00000000000..a40907106a2 --- /dev/null +++ b/docs/diagrams/DeleteTaskActivityDiagram.puml @@ -0,0 +1,18 @@ +@startuml +start +:User types in the +delete task command; + +'Since the beta syntax does not support placing the condition outside the +'diamond we place it as the true branch instead. + +if () then ([Valid format and/or input]) + :Corresponding task is + removed from Tasklist; + :Prompt user that the task + has been successfully deleted; +else ([Invalid Format Used]) + -Prompt user with the command's format +endif +stop +@enduml \ No newline at end of file diff --git a/docs/diagrams/DeleteTaskSequenceDiagram.puml b/docs/diagrams/DeleteTaskSequenceDiagram.puml new file mode 100644 index 00000000000..4d76d1fd955 --- /dev/null +++ b/docs/diagrams/DeleteTaskSequenceDiagram.puml @@ -0,0 +1,63 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":DeleteTaskCommandParser" as DeleteTaskCommandParser LOGIC_COLOR +participant "d:DeleteTaskCommand" as DeleteTaskCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Tasklist MODEL_COLOR_T1 +participant "taskList:Tasklist" as Model MODEL_COLOR +end box + +[-> LogicManager : execute("delt 1") +activate LogicManager + +LogicManager -> AddressBookParser : parseCommand("delt 1") +activate AddressBookParser + +create DeleteTaskCommandParser +AddressBookParser -> DeleteTaskCommandParser +activate DeleteTaskCommandParser + +create DeleteTaskCommand +DeleteTaskCommandParser -> DeleteTaskCommand +activate DeleteTaskCommand + +DeleteTaskCommand --> DeleteTaskCommandParser : d +deactivate DeleteTaskCommand + +DeleteTaskCommandParser --> AddressBookParser : d +deactivate DeleteTaskCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +DeleteTaskCommandParser -[hidden]-> AddressBookParser +destroy DeleteTaskCommandParser + +AddressBookParser --> LogicManager : d +deactivate AddressBookParser + +LogicManager -> DeleteTaskCommand : execute(model) +activate DeleteTaskCommand + +DeleteTaskCommand -> Model : deleteTask(1) +activate Model + +Model --> DeleteTaskCommand +deactivate Model + +create CommandResult +DeleteTaskCommand -> CommandResult +activate CommandResult + +CommandResult --> DeleteTaskCommand +deactivate CommandResult + +DeleteTaskCommand --> LogicManager : result +deactivate DeleteTaskCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/images/DeleteTaskActivityDiagram.png b/docs/images/DeleteTaskActivityDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..abf1fe638e2fea9bb39f09dd6adace2e6aea6843 GIT binary patch literal 21510 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

@@ -32,31 +33,34 @@ - - - - - - - - - - - - + - + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/TaskCard.fxml b/src/main/resources/view/TaskCard.fxml index e482482afe2..3e778e53c7a 100644 --- a/src/main/resources/view/TaskCard.fxml +++ b/src/main/resources/view/TaskCard.fxml @@ -20,7 +20,6 @@ diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/ThemePresets.css similarity index 78% rename from src/main/resources/view/DarkTheme.css rename to src/main/resources/view/ThemePresets.css index 36e6b001cd8..fd914a83824 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/ThemePresets.css @@ -1,5 +1,5 @@ .background { - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#fffff0, 20%); background-color: #383838; /* Used in the default.html file */ } @@ -40,9 +40,9 @@ } .table-view { - -fx-base: #1d1d1d; - -fx-control-inner-background: #1d1d1d; - -fx-background-color: #1d1d1d; + -fx-base: #f0ffff; + -fx-control-inner-background: #f0ffff; + -fx-background-color: #f0ffff; -fx-table-cell-border-color: transparent; -fx-table-header-border-color: transparent; -fx-padding: 5; @@ -77,47 +77,50 @@ } .split-pane:horizontal .split-pane-divider { - -fx-background-color: derive(#1d1d1d, 20%); - -fx-border-color: transparent transparent transparent #4d4d4d; + -fx-background-color: derive(#f0ffff, 20%); + -fx-border-color: derive(#f0ffff, 20%); } .split-pane { - -fx-border-radius: 1; -fx-border-width: 1; - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#f0ffff, 20%); } .list-view { -fx-background-insets: 0; -fx-padding: 0; - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#f0ffff, 20%); } .list-cell { -fx-label-padding: 0 0 0 0; -fx-graphic-text-gap : 0; - -fx-padding: 0 0 0 0; + -fx-background-insets: 3px; + -fx-background-radius: 15; } .list-cell:filled:even { - -fx-background-color: #3c3e3f; + -fx-background-color: #e8eaf6; } .list-cell:filled:odd { - -fx-background-color: #515658; + -fx-background-color: #dadef1; } .list-cell:filled:selected { - -fx-background-color: #424d5f; + -fx-background-color: #d2d4e0; } .list-cell:filled:selected #cardPane { + -fx-label-padding: 0 0 0 0; -fx-border-color: #3e7b91; -fx-border-width: 1; + -fx-background-insets: 3px; + -fx-border-radius: 15; } .list-cell .label { - -fx-text-fill: white; + -fx-text-fill: black; } .cell_big_label { @@ -133,24 +136,25 @@ } .stack-pane { - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#f0ffff, 20%); + -fx-border-color: derive(#1d1d1d, 40%); } .pane-with-border { - -fx-background-color: derive(#1d1d1d, 20%); - -fx-border-color: derive(#1d1d1d, 10%); + -fx-background-color: derive(#fffff0, 20%); + -fx-border-color: derive(#1d1d1d, -10%); -fx-border-top-width: 1px; } .status-bar { - -fx-background-color: derive(#1d1d1d, 30%); + -fx-background-color: #c9f1fd; } .result-display { - -fx-background-color: transparent; + -fx-background-color: derive(#fffff0, 20%); -fx-font-family: "Segoe UI Light"; -fx-font-size: 13pt; - -fx-text-fill: white; + -fx-text-fill: black; } .result-display .label { @@ -159,7 +163,7 @@ .status-bar .label { -fx-font-family: "Segoe UI Light"; - -fx-text-fill: white; + -fx-text-fill: black; -fx-padding: 4px; -fx-pref-height: 30px; } @@ -181,11 +185,11 @@ } .grid-pane .stack-pane { - -fx-background-color: derive(#1d1d1d, 30%); + -fx-background-color: derive(#fffff0, 30%); } .context-menu { - -fx-background-color: derive(#1d1d1d, 50%); + -fx-background-color: derive(#fffff0, 30%); } .context-menu .label { @@ -199,14 +203,24 @@ .menu-bar .label { -fx-font-size: 14pt; -fx-font-family: "Segoe UI Light"; - -fx-text-fill: white; + -fx-text-fill: black; -fx-opacity: 0.9; } .menu .left-container { - -fx-background-color: black; + -fx-background-color: #c9f1fd; } +.menu-item .label{ + -fx-background-color: #c9f1fd; + -fx-text-fill: black; +} + +.context-menu { + -fx-background-color: #c9f1fd; + -fx-border-color: #1d1d1d; + -fx-border-width: 1; +} /* * Metro style Push Button * Author: Pedro Duque Vieira @@ -267,11 +281,11 @@ .dialog-pane > *.label.content { -fx-font-size: 14px; -fx-font-weight: bold; - -fx-text-fill: white; + -fx-text-fill: black; } .dialog-pane:header *.header-panel { - -fx-background-color: derive(#1d1d1d, 25%); + -fx-background-color: derive(#f0ffff, 20%); } .dialog-pane:header *.header-panel *.label { @@ -282,12 +296,15 @@ } .scroll-bar { - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#e6e6e7, 20%); } .scroll-bar .thumb { - -fx-background-color: derive(#1d1d1d, 50%); + -fx-background-color: #e6e6e7; -fx-background-insets: 3; + -fx-border-color: #2d4b5a; + -fx-background-radius : 1em; + -fx-border-radius: 1em; } .scroll-bar .increment-button, .scroll-bar .decrement-button { @@ -318,6 +335,7 @@ } #commandTextField { + -fx-prompt-text-fill: black; -fx-background-color: transparent #383838 transparent #383838; -fx-background-insets: 0; -fx-border-color: #383838 #383838 #ffffff #383838; @@ -325,7 +343,7 @@ -fx-border-width: 1; -fx-font-family: "Segoe UI Light"; -fx-font-size: 13pt; - -fx-text-fill: white; + -fx-text-fill: black; } #filterField, #personListPanel, #personWebpage { @@ -333,7 +351,7 @@ } #resultDisplay .content { - -fx-background-color: transparent, #383838, transparent, #383838; + -fx-background-color: derive(#f0ffff, 20%); -fx-background-radius: 0; } From 847b08ecdf61205c1d5863fbb5d88f4cbef8f72c Mon Sep 17 00:00:00 2001 From: yumengtan Date: Fri, 1 Apr 2022 03:17:16 +0800 Subject: [PATCH 082/140] Update UG --- docs/UserGuide.md | 135 ++++++++++++++++++++++++--------------------- docs/images/Ui.png | Bin 26434 -> 35399 bytes 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b2bd76aee8a..3aaeb3823c2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -38,15 +38,18 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona 5. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: - 1. `view c` : Lists all contacts. - 2. `add c` /John Doe /[johnd@example.com](mailto:johnd@example.com) /johntele: Adds a contact named John Doe to the Address Book. - 3. `add tn/Assignment 1 m/CS1101s` : Adds an `assignment/task` of the specified module to NUScheduler. - 4. `del c 3` : Deletes the 3rd contact shown in the current list. - 5. `delt 3` : Deletes the 3rd task shown in the current task list. - 6. `upd t 3 n/Assignment 2 m/CS1231s` : Updates the specified task in the current list. - 7. `exit` : Exits the app. - -6. Refer to the [Features](#features) below for details of each command. + 1. `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. + 2. `addt d/Buy groceries t/01/01/2022` : Adds an `assignment/task` to NUScheduler. + 3. `delele 3` : Deletes the 3rd contact shown in the current list. + 4. `delt 3` : Deletes the 3rd task shown in the current task list. + 5. `findt assignment 1` : Finds any tasks in the current task list that contains the keyword(s). + 6. `upd t d 3 /Buy groceries` : Updates the specified task in the current list. + 7. `viewt` : Lists all tasks. + 8. `list` : Lists all contacts. + 9. `clear` : Deletes all contacts. + 10. `exit` : Exits the app. + +7. Refer to the [Features](#features) below for details of each command. -------------------------------------------------------------------------------------------------------------------- @@ -71,9 +74,9 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona Adds a task to the task list. -Format: `addt d/DESCRIPTION [t/DEADLINE (dd/mm/yyyy)]` +Format: `addt d/DESCRIPTION t/DEADLINE (dd/mm/yyyy)` -Example: `addt d/Buy groceries [t/01/01/2022]` +Example: `addt d/Buy groceries t/01/01/2022` ### Feature - Delete a task: `delt ` @@ -99,7 +102,7 @@ Format: `upd t t /DEADLINE` Example: `upd t t /2022 03 10 12pm` -### Feature - Find tasks: `findt KEYWORD` +### Feature - Find tasks: `findt KEYWORD [MORE_KEYWORDS]` Locating tasks which match any of given keywords. @@ -108,6 +111,7 @@ Format:  `findt KEYWORD` - The search is case-insensitive. e.g. `lessons` will match `Lessons`. - The order of the keywords matters. e.g. `drink water` will not match `water drink` - Only full keyword(s) will be accepted. e.g. `drink` will match `drink`; `ink` will not match `drink` +- All keyword(s) have to be matched for task to be returned. Example: `findt lessons` returns `Swimming lessons 03/05/2022`. @@ -117,65 +121,62 @@ View all the tasks currently in the task list. Format: `viewt` -### Feature - Add contact: `add c` +### Feature - Adding a contact: `add` -Adds a person to address book. +Adds a person to the address book. -Format: `add c /NAME /EMAIL /TELEGRAM [/TAG]` +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` -The Telegram handle can be entered with or without an @ symbol in front. +
:bulb: **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` -- `add c /John Doe /johnd@example.com /johndtele /Group Member` -- `add c /Betsy Crow /betsycrow@example.com /betsyc` - -### Feature - Delete contact: `del c ` - -Deletes a contact from the contact list. - -Format: `del c ` - -Example: `del c 3` - -### Feature - Update contact: `upd c ` - -Updates a contact from the contact list. +### Feature - Deleting a contact : `delete` -Format:  `upd c /NAME /EMAIL /TELEGRAM [/TAG] ` +Deletes the specified person from the address book. -Update a contact’s information, where `` is the contact’s unique identifier. +Format: `delete INDEX` -Example: `upd c /John Doe  /johndoe@example.com /johntele 23` +* Deletes the person at the specified `INDEX`. +* The index refers to the index number shown in the displayed contact list. +* The index **must be a positive integer** 1, 2, 3, …​ -### Feature - View all contacts: `view c` +Examples: +* `list` followed by `delete 2` deletes the 2nd contact in the address book. +* `find Betsy` followed by `delete 1` deletes the 1st contact in the results of the `find` command. -View all the contacts currently in the contact list. +### Feature: Editing a contact : `edit` -Format: `view c [to] [t] [/TAG]` +Edits an existing contact in the address book. -The optional parameter `[to]` will return the contact list in tag order instead of the default alphabetical order. +Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` -The optional parameter `[t]` requires a tag input and will return contacts from that tag only. +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. 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 contact to be `91234567` and `johndoe@example.com` respectively. +* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd contact to be `Betsy Crower` and clears all existing tags. -- `view c` -- `view c to` -- `view c t /Friends` - -### Feature - Remind the user of upcoming tasks: `remind` +### Listing all contacts : `list` -Reminds the user of all the tasks with upcoming deadlines (within 7 days by default). +Shows a list of all contacts in the address book. -Format: `remind []` +Format: `list` -The optional `[]` specifies the number of days to check tasks against and return. +### Clearing all contact entries : `clear` -Tasks are returned in ascending order of time to deadline (closest deadline first). - -Example: `remind 10` +Clears all entries from the address book. +Format: `clear` ### Feature - Exit the app: `exit` Exits the app. @@ -184,7 +185,16 @@ Format: exit ### Feature - Saving the data -NUScheduler data is saved in the hard disk automatically after any command that changes the data. There is no manual save function. +NUScheduler data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. + +### Feature - Editing the data file + +NUScheduler data are saved as a JSON file `[JAR file location]/data/addressbook.json` for address book and `[JAR file location]/data/tasklist.json`. +Advanced users are welcome to update data directly by editing that data file. + +
:exclamation: **Caution:** +If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. +
-------------------------------------------------------------------------------------------------------------------- @@ -199,16 +209,15 @@ data of your previous NUScheduler home folder. ## Command summary -| Action | Format, Examples | -|-----------------------|-------------------------------------------------------------------------------------------------------------------| -| **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | -| **delt ** | `del t `
e.g., `del t 3` | -| **upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` | -| **upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` | -| **findt KEYWORD** | `findt `
e.g., `findt lessons` | -| **viewt** | `view t` | -| **add c** | `add c /NAME /EMAIL /TELEGRAM [/TAG]`
e.g., `add c /Betsy Crow /betsycrow@example.com /betsyc /Group Member` | -| **del c ** | `del c `
e.g., `del c 3` | -| **upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` | -| **view c** | `view c [to] [t] [/TAG]`
e.g., `view c` | -| **exit** | `exit` | +| Action | Format, Examples | +|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | +| **delt ** | `del t `
e.g., `del t 3` | +| **updt d ** | `updt d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` | +| **updt t ** | `updt t /DEADLINE`
e.g.,`updt t /2022 03 10 12pm` | +| **findt ** | `findt `
e.g., `findt lessons`, `findt swimming lessons` | +| **viewt** | `viewt` | +| **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` | +| **del c ** | `del c `
e.g., `del c 3` | +| **edit ** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | +| **exit** | `exit` | diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 9d9dff887ead8975fafb9a043a5d4abab167d97f..fcdee05c7c763351c3ec459ce45d6e14d61c62ac 100644 GIT binary patch literal 35399 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 OXK7)3y5!`wd;bGj7!fJ} literal 26434 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 Date: Fri, 1 Apr 2022 03:38:46 +0800 Subject: [PATCH 083/140] Modified UG --- docs/UserGuide.md | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3aaeb3823c2..8dcf8a1fe8b 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,12 +13,14 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona - Add task - Delete task - Update task + - Find task - View all tasks and their deadlines - Contact Management - Add contact - Delete contact - - Update contact - - View all contacts + - Edit contact + - List all contacts + - Clear all contacts - Exit the app - FAQ - CLI Summary @@ -61,11 +63,11 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona **Notes about the command format:** -- Words in **UPPER_CASE** are the parameters to be supplied by the user.e.g. in `add t n /NAME`, **NAME** is a parameter. -- which can be used as `add t n /John Doe`. -- Items in **square brackets** are optional.e.g `/NAME [/TAG]` can be used as `/John Doe /friend` or as `/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`. - Parameters cannot be in any order and must follow the order given in the command format.e.g. if the command format. -- specifies `add t /DESCRIPTION /DEADLINE [/TAG]`, the details must be entered as `/DESCRIPTION /DEADLINE [/TAG]`. +- specifies `addt d/DESCRIPTION [t/DEADLINE]`, the details must be entered as `d/DESCRIPTION [t/DEADLINE]`. - All `` fields must be > 0. @@ -86,27 +88,23 @@ Format: `delt ` Example: `delt 3` -### Feature - Update a task description: `upd t d ` +### Feature - Update a task description and/or deadline: `updt` Updates a task in the task list, where `` is the ID of the task. -Format: `upd t d   /DESCRIPTION` +Format: `updt [d/DESCRIPTION] [t/DEADLINE]` -Example: `upd t d 3 /Buy groceries` +Example: `updt 3 d/Buy groceries t/01/02/2022` -### Feature - Update a task deadline: `upd t t ` +Example: `updt 3 d/Buy groceries` -Updates a task in the task list, where `` is the ID of the task. - -Format: `upd t t /DEADLINE` - -Example: `upd t t /2022 03 10 12pm` +Example: `updt 3 t/01/02/2022` -### Feature - Find tasks: `findt KEYWORD [MORE_KEYWORDS]` +### Feature - Find tasks: `findt` Locating tasks which match any of given keywords. -Format:  `findt KEYWORD` +Format: `findt KEYWORD [MORE_KEYWORDS]` - The search is case-insensitive. e.g. `lessons` will match `Lessons`. - The order of the keywords matters. e.g. `drink water` will not match `water drink` @@ -139,9 +137,9 @@ Examples: Deletes the specified person from the address book. -Format: `delete INDEX` +Format: `delete ` -* Deletes the person at the specified `INDEX`. +* Deletes the person at the specified ``. * The index refers to the index number shown in the displayed contact list. * The index **must be a positive integer** 1, 2, 3, …​ @@ -212,12 +210,11 @@ data of your previous NUScheduler home folder. | Action | Format, Examples | |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | -| **delt ** | `del t `
e.g., `del t 3` | -| **updt d ** | `updt d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` | -| **updt t ** | `updt t /DEADLINE`
e.g.,`updt t /2022 03 10 12pm` | +| **delt ** | `delt `
e.g., `del t 3` | +| **updt [d/DESCRIPTION] [t/DEADLINE]** | `updt [d/DESCRIPTION] [t/DEADLINE]`
e.g., `updt 3 d/Buy groceries t/01/01/2022` | | **findt ** | `findt `
e.g., `findt lessons`, `findt swimming lessons` | | **viewt** | `viewt` | | **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` | -| **del c ** | `del c `
e.g., `del c 3` | -| **edit ** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | +| **del ** | `del `
e.g., `del 3` | +| **edit ** | `edit [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | | **exit** | `exit` | From 4b261b8bd2dcc06656f2fa80f98b923affc5d3cc Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Fri, 1 Apr 2022 03:48:22 +0800 Subject: [PATCH 084/140] More UG updates --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8dcf8a1fe8b..50e1e23ff0a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -31,7 +31,7 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona 1. Ensure you have `Java 11` or above installed in your Computer. -2. Download the latest `NUScheduler.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). +2. Download the latest `NUScheduler.jar` from [here](https://github.com/AY2122S2-CS2103-F11-4/tp/releases/tag/v1.3). 3. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. @@ -45,7 +45,7 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona 3. `delele 3` : Deletes the 3rd contact shown in the current list. 4. `delt 3` : Deletes the 3rd task shown in the current task list. 5. `findt assignment 1` : Finds any tasks in the current task list that contains the keyword(s). - 6. `upd t d 3 /Buy groceries` : Updates the specified task in the current list. + 6. `updt 3 d/Buy groceries` : Updates the specified task in the current list. 7. `viewt` : Lists all tasks. 8. `list` : Lists all contacts. 9. `clear` : Deletes all contacts. From b51ae93bd1a628b82e4432e48906b515b081b8ce Mon Sep 17 00:00:00 2001 From: yumengtan Date: Fri, 1 Apr 2022 10:39:23 +0800 Subject: [PATCH 085/140] Update regex to match whole words only --- src/main/java/seedu/address/model/TaskList.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 756acb0336c..3277e06e875 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import javafx.collections.ObservableList; import seedu.address.logic.commands.exceptions.CommandException; @@ -108,7 +109,8 @@ public String findTask(String input) { ArrayList matchingTasks = new ArrayList<>(); for (int i = 0; i < this.taskList.size(); i++) { Task curr = this.taskList.get(i); - if (curr.toString().matches("(?i).*" + input + ".*")) { //bypass case sensitivity with regex + String pattern = "(?i)(? Date: Fri, 1 Apr 2022 12:52:53 +0800 Subject: [PATCH 086/140] Minor update to UG --- docs/UserGuide.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 50e1e23ff0a..98f40f87854 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -140,8 +140,8 @@ Deletes the specified person from the address book. Format: `delete ` * Deletes the person at the specified ``. -* The index refers to the index number shown in the displayed contact list. -* The index **must be a positive integer** 1, 2, 3, …​ +* The integer refers to the index number shown in the displayed contact list. +* The integer **must be a positive integer** 1, 2, 3, … Examples: * `list` followed by `delete 2` deletes the 2nd contact in the address book. @@ -151,9 +151,9 @@ Examples: Edits an existing contact in the address book. -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +Format: `edit INTEGER [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 displayed person list. The index **must be a positive integer** 1, 2, 3, …​ +* Edits the person at the specified `INTEGER`. The integer refers to the index number shown in the displayed person list. The integer **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. @@ -179,7 +179,7 @@ Format: `clear` Exits the app. -Format: exit +Format: `exit` ### Feature - Saving the data @@ -210,11 +210,11 @@ data of your previous NUScheduler home folder. | Action | Format, Examples | |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | -| **delt ** | `delt `
e.g., `del t 3` | -| **updt [d/DESCRIPTION] [t/DEADLINE]** | `updt [d/DESCRIPTION] [t/DEADLINE]`
e.g., `updt 3 d/Buy groceries t/01/01/2022` | -| **findt ** | `findt `
e.g., `findt lessons`, `findt swimming lessons` | +| **delt** | `delt `
e.g., `del t 3` | +| **updt** | `updt [d/DESCRIPTION] [t/DEADLINE]`
e.g., `updt 3 d/Buy groceries t/01/01/2022` | +| **findt** | `findt `
e.g., `findt lessons`, `findt swimming lessons` | | **viewt** | `viewt` | | **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` | -| **del ** | `del `
e.g., `del 3` | -| **edit ** | `edit [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | +| **del** | `del `
e.g., `del 3` | +| **edit** | `edit [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | | **exit** | `exit` | From 83d2ab3a920ea60449085da182bfa97129daa8ec Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 5 Apr 2022 15:41:05 +0800 Subject: [PATCH 087/140] Fix incorrect error message in delete command Fix UpdateTaskCommand bug of deleting task when duplicate task received --- .../seedu/address/logic/commands/DeleteTaskCommand.java | 2 +- .../seedu/address/logic/commands/UpdateTaskCommand.java | 6 +----- .../address/logic/parser/DeleteTaskCommandParser.java | 3 +-- .../address/logic/parser/UpdateTaskCommandParser.java | 7 ++++--- src/main/java/seedu/address/model/task/UniqueTaskList.java | 3 --- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java index 936b82895dc..5c4be7fe5f6 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteTaskCommand.java @@ -13,7 +13,7 @@ public class DeleteTaskCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Delete a task number from current tasklist using given index. \n" - + "Format: delt [tasknumber]. \n" + + "Format: delt . \n" + "Example: " + COMMAND_WORD + " " + "1"; public static final String MESSAGE_ARGUMENTS = "Task %1$s deleted"; diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java index 24e6cf930bb..6f041129209 100644 --- a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -24,9 +24,9 @@ public class UpdateTaskCommand extends Command { + PREFIX_ADD_TASK_DESCRIPTION + "Running Lesson " + PREFIX_ADD_TASK_DEADLINE + "04/05/2022"; + public static final String MESSAGE_EMPTY_PARAMETERS = "Parameter given cannot be blank"; public static final String MESSAGE_UPDATE_TASK_SUCCESS = "Updated Task: %1$s"; public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; - public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task list."; public static final String MESSAGE_INVALID_TASK_DISPLAYED_ID = "The task id provided is invalid"; private final Integer taskId; @@ -56,10 +56,6 @@ public CommandResult execute(Model model) throws CommandException { Task taskToUpdate = lastShownList.getTask(taskId); Task updatedTask = createUpdatedTask(taskToUpdate, updateTaskDescriptor); - if (taskToUpdate.equals(updatedTask)) { - throw new CommandException(MESSAGE_DUPLICATE_TASK); - } - model.updateTask(updatedTask, taskId); return new CommandResult(String.format(MESSAGE_UPDATE_TASK_SUCCESS, updatedTask)); diff --git a/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java index f177071a7ed..3f9713109d9 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/DeleteTaskCommandParser.java @@ -3,7 +3,6 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DeleteTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -24,7 +23,7 @@ public DeleteTaskCommand parse(String args) throws ParseException { return new DeleteTaskCommand(taskNumber); } catch (ParseException pe) { throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE), pe); } } diff --git a/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java index 4f93a208557..14d3113465f 100644 --- a/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java @@ -9,7 +9,6 @@ import java.time.format.DateTimeParseException; import java.util.List; -import seedu.address.logic.commands.AddTaskCommand; import seedu.address.logic.commands.UpdateTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -105,13 +104,15 @@ private void checkEmptyPrefix(ArgumentMultimap argMultimap) throws ParseExceptio if (argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).isPresent()) { String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); if (description.equals("")) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UpdateTaskCommand.MESSAGE_EMPTY_PARAMETERS)); } } if (argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).isPresent()) { String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); if (deadline.equals("")) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UpdateTaskCommand.MESSAGE_EMPTY_PARAMETERS)); } } } diff --git a/src/main/java/seedu/address/model/task/UniqueTaskList.java b/src/main/java/seedu/address/model/task/UniqueTaskList.java index b4c9c107d58..ca1fbcf92ad 100644 --- a/src/main/java/seedu/address/model/task/UniqueTaskList.java +++ b/src/main/java/seedu/address/model/task/UniqueTaskList.java @@ -53,9 +53,6 @@ public void addTask(Task task) { public void addTask(Task toAdd, Integer taskId) throws CommandException { requireNonNull(toAdd); requireNonNull(taskId); - if (contains(toAdd)) { - throw new CommandException("Duplicate Task received"); - } internalList.add(taskId - 1, toAdd); // to convert to zero-based indexing } From 20612135b006a40885100158a413ae6c907dbeab Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 5 Apr 2022 15:49:40 +0800 Subject: [PATCH 088/140] Fix checkstyle error and remove irrelevant test case --- .../logic/commands/UpdateTaskCommandTest.java | 12 ------------ .../logic/parser/DeleteTaskCommandParserTest.java | 5 ++--- .../seedu/address/model/task/UniqueTaskListTest.java | 5 ----- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java index 0d109f01e25..bfcac13d122 100644 --- a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java @@ -63,18 +63,6 @@ public void createTaskWithoutDeadline_descriptorWithoutDeadline() { assertTrue(newTaskCreated.getDeadline().equals("No deadline set")); } - @Test - public void execute_updateDuplicateTask_failure() throws CommandException { - Task updatedTask = new Task("test", "03/03/2022"); - UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); - descriptor.setDescription(updatedTask.getDescription()); - descriptor.setDeadline(updatedTask.getDeadline()); - UpdateTaskCommand updateTaskCommand = new UpdateTaskCommand(1, descriptor); - model.updateTask(updatedTask, 1); - model.updateTask(updatedTask, 1); // throw duplicate task error - - assertCommandFailure(updateTaskCommand, model, "This task already exists in the task list."); - } @Test public void execute_invalidPersonIndexUnfilteredList_failure() { diff --git a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java index 11257bd7ef6..00d32adb787 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteTaskCommandParserTest.java @@ -7,7 +7,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.DeleteCommand; import seedu.address.logic.commands.DeleteTaskCommand; @@ -23,13 +22,13 @@ public void parse_validArgs_returnsDeleteCommand() { @Test public void parse_invalidArgs_throwsParseException() { assertParseFailure(parser, "a", - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE)); } @Test public void parse_invalidSymbols_throwsParseException() { assertParseFailure(parser, "$%^%$^%#$", - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE)); } } diff --git a/src/test/java/seedu/address/model/task/UniqueTaskListTest.java b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java index c91d067d39a..3d55e27bec9 100644 --- a/src/test/java/seedu/address/model/task/UniqueTaskListTest.java +++ b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java @@ -36,11 +36,6 @@ public void add_nullTask_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> uniqueTaskList.addTask(null)); } - @Test - public void add_duplicateTask_throwsDuplicatePersonException() throws CommandException { - uniqueTaskList.addTask(DUMMY_TASK, 1); - assertThrows(CommandException.class, () -> uniqueTaskList.addTask(DUMMY_TASK, 1)); - } @Test public void remove_nullTask_throwsNullPointerException() { From ba1e9f58ab1993336562c42441be7b752a4d23b0 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 6 Apr 2022 20:59:23 +0800 Subject: [PATCH 089/140] Update UG based on PED bug reports --- docs/UserGuide.md | 204 ++++++++++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 79 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 98f40f87854..4bf2dd9fff8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,28 +2,29 @@ layout: page title: User Guide --- -#User Guide - NUScheduler +# User Guide - NUScheduler NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. -- Quick Start -- Features - - Task Management - - Add task - - Delete task - - Update task - - Find task - - View all tasks and their deadlines - - Contact Management - - Add contact - - Delete contact - - Edit contact - - List all contacts - - Clear all contacts - - Exit the app -- FAQ -- CLI Summary +- [Quick Start](#quick-start) +- [Features](#features) + - [Task Management](#task-management) + - [Add task](#feature-1) + - [Delete task](#feature-2) + - [Update task](#feature-3) + - [Find task](#feature-4) + - [View all tasks and their deadlines](#feature-5) + - [Contact Management](#contact-management) + - [Add contact](#feature-6) + - [Delete contact](#feature-7) + - [Edit contact](#feature-8) + - [List all contacts](#feature-9) + - [Clear all contacts](#feature-10) + - [Find all contacts](#feature-11) + - [Exit the app](#feature-12) +- [FAQ](#faq) +- [Command Summary](#command-summary) -------------------------------------------------------------------------------------------------------------------- @@ -33,19 +34,20 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona 2. Download the latest `NUScheduler.jar` from [here](https://github.com/AY2122S2-CS2103-F11-4/tp/releases/tag/v1.3). -3. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +3. Copy the file to the folder you want to use as the _home folder_ for your NUScheduler. 4. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- ![Ui](images/Ui.png) + +![Ui](images/Ui.png) -5. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+6. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: - 1. `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. - 2. `addt d/Buy groceries t/01/01/2022` : Adds an `assignment/task` to NUScheduler. - 3. `delele 3` : Deletes the 3rd contact shown in the current list. - 4. `delt 3` : Deletes the 3rd task shown in the current task list. - 5. `findt assignment 1` : Finds any tasks in the current task list that contains the keyword(s). - 6. `updt 3 d/Buy groceries` : Updates the specified task in the current list. + 1. `add n/Beow Tan p/9123 4157 e/beow@example.com a/Jurong street 11, block 123, #01-01` : Adds a contact named Beow Tan to NUScheduler. + 2. `addt d/CS2105 Assignment 1 t/01/03/2022` : Adds an `assignment/task` to NUScheduler. + 3. `delete 1` : Deletes the 1st contact shown in the current list. + 4. `delt 1` : Deletes the 1st task shown in the current task list. + 5. `findt swimming lesson` : Finds any tasks in the current task list that contains the keyword(s). + 6. `updt 1 d/CS2102 Assignment 1` : Updates the specified task in the current list. 7. `viewt` : Lists all tasks. 8. `list` : Lists all contacts. 9. `clear` : Deletes all contacts. @@ -68,41 +70,56 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona - 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`. - Parameters cannot be in any order and must follow the order given in the command format.e.g. if the command format. - specifies `addt d/DESCRIPTION [t/DEADLINE]`, the details must be entered as `d/DESCRIPTION [t/DEADLINE]`. -- All `` fields must be > 0. +- All `` fields must be > 0. +- Additional parameters for commands that do not take in any parameters (such as `list`) will be ignored. + e.g. if you input `list aa`, NUScheduler will understand it as `list`. -### Feature - Add a task: `addt` +## Task Management -Adds a task to the task list. +-------------------------------------------------------------------------------------------------------------------- + + +### Feature 1 +#### Add Task - Adds a task: `addt` + +Adds a task to the task list. There will be no restriction on duplicate tasks. -Format: `addt d/DESCRIPTION t/DEADLINE (dd/mm/yyyy)` +Format: `addt d/DESCRIPTION [t/DEADLINE (dd/mm/yyyy)]` Example: `addt d/Buy groceries t/01/01/2022` -### Feature - Delete a task: `delt ` +### Feature 2 +#### Feature - Deletes a task: `delt` -Deletes a task from the task list, where `` is the ID of the task. +Deletes a task from the task list, where `` is the ID of the task. -Format: `delt ` +Format: `delt ` Example: `delt 3` -### Feature - Update a task description and/or deadline: `updt` +### Feature 3 +#### Feature - Updates a task description and/or deadline: `updt` -Updates a task in the task list, where `` is the ID of the task. +Updates a task in the task list, where `` is the ID of the task. At least one parameter must be provided. -Format: `updt [d/DESCRIPTION] [t/DEADLINE]` +Format 1: `updt t/DEADLINE` -Example: `updt 3 d/Buy groceries t/01/02/2022` +Format 2: `updt d/DESCRIPTION` -Example: `updt 3 d/Buy groceries` +Format 3: `updt d/DESCRIPTION t/DEADLINE` -Example: `updt 3 t/01/02/2022` +Example 1: `updt 3 t/01/02/2022` -### Feature - Find tasks: `findt` +Example 2: `updt 3 d/Buy groceries` -Locating tasks which match any of given keywords. +Example 3: `updt 3 d/Buy groceries t/01/02/2022` + +### Feature 4 +#### Feature - Find tasks: `findt` + +Locating tasks which match any of given keyword(s). Format: `findt KEYWORD [MORE_KEYWORDS]` @@ -113,85 +130,111 @@ Format: `findt KEYWORD [MORE_KEYWORDS]` Example: `findt lessons` returns `Swimming lessons 03/05/2022`. -### Feature - List all tasks: `viewt` +### Feature 5 +#### Feature - List all tasks: `viewt` View all the tasks currently in the task list. Format: `viewt` -### Feature - Adding a contact: `add` +## Contact Management + +-------------------------------------------------------------------------------------------------------------------- + +### Feature 6 +#### Feature - Adds a contact: `add` -Adds a person to the address book. +Adds a contact to NUScheduler. Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
:bulb: **Tip:** -A person can have any number of tags (including 0) +A contact 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` -### Feature - Deleting a contact : `delete` +### Feature 7 +#### Feature - Deletes a contact : `delete` -Deletes the specified person from the address book. +Deletes the specified contact from NUScheduler. Format: `delete ` -* Deletes the person at the specified ``. +* Deletes the contact at the specified ``. * The integer refers to the index number shown in the displayed contact list. -* The integer **must be a positive integer** 1, 2, 3, … +* The integer **must be a positive integer**. Examples: -* `list` followed by `delete 2` deletes the 2nd contact in the address book. +* `list` followed by `delete 2` deletes the 2nd contact in NUScheduler. * `find Betsy` followed by `delete 1` deletes the 1st contact in the results of the `find` command. -### Feature: Editing a contact : `edit` +### Feature 8 +#### Feature - Edits a contact : `edit` -Edits an existing contact in the address book. +Edits an existing contact in the NUScheduler. -Format: `edit INTEGER [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +Format: `edit [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` -* Edits the person at the specified `INTEGER`. The integer refers to the index number shown in the displayed person list. The integer **must be a positive integer** 1, 2, 3, … +* Edits the contact at the specified `INTEGER`. The integer refers to the index number shown in the displayed contact list. The integer **must be a positive integer**. * 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 + * Existing values will be updated to the input values. +* When editing tags, the existing tags of the contact will be removed i.e adding of tags is not cumulative. +* You can remove all the contact’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 contact to be `91234567` and `johndoe@example.com` respectively. * `edit 2 n/Betsy Crower t/` Edits the name of the 2nd contact to be `Betsy Crower` and clears all existing tags. -### Listing all contacts : `list` +### Feature 9 +#### Feature - List all contacts : `list` -Shows a list of all contacts in the address book. +Shows a list of all contacts in NUScheduler. Format: `list` -### Clearing all contact entries : `clear` +### Feature 10 +#### Feature - Clears all contact entries : `clear` -Clears all entries from the address book. +Clears all contacts from NUScheduler. Format: `clear` -### Feature - Exit the app: `exit` + +### Feature 11 +#### Feature - Finds contacts containing any of the given keywords: `find` + +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` +* Contacts 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 alex david` returns `Alex Yeoh`, `David Li`
+ +### Feature 12 +#### Feature - Exit the app: `exit` Exits the app. Format: `exit` -### Feature - Saving the data - NUScheduler data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually. -### Feature - Editing the data file +### Note - Editing the data file -NUScheduler data are saved as a JSON file `[JAR file location]/data/addressbook.json` for address book and `[JAR file location]/data/tasklist.json`. +NUScheduler data are saved as a JSON file `[JAR file location]/data/addressbook.json` for contact list and `[JAR file location]/data/tasklist.json` for task list. Advanced users are welcome to update data directly by editing that data file.
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. +If your changes to the data file makes its format invalid, NUScheduler will discard all data and start with an empty data file at the next run.
-------------------------------------------------------------------------------------------------------------------- @@ -207,14 +250,17 @@ data of your previous NUScheduler home folder. ## Command summary -| Action | Format, Examples | -|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | -| **delt** | `delt `
e.g., `del t 3` | -| **updt** | `updt [d/DESCRIPTION] [t/DEADLINE]`
e.g., `updt 3 d/Buy groceries t/01/01/2022` | -| **findt** | `findt `
e.g., `findt lessons`, `findt swimming lessons` | -| **viewt** | `viewt` | -| **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` | -| **del** | `del `
e.g., `del 3` | -| **edit** | `edit [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | -| **exit** | `exit` | +| Action | Format, Examples | +|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **addt** | `addt d/DESCRIPTION [t/DEADLINE]`
e.g., `addt d/Buy groceries [t/2022 02 22 5pm]` | +| **delt** | `delt `
e.g., `delt 3` | +| **updt** | `updt [d/DESCRIPTION] [t/DEADLINE]`
e.g., `updt 3 d/Buy groceries t/01/01/2022` | +| **findt** | `findt KEYWORD [MORE_KEYWORDS]`
e.g., `findt swimming lessons` | +| **viewt** | `viewt` | +| **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` | +| **delete** | `delete `
e.g., `delete 3` | +| **list** | `list` | +| **clear** | `clear` | +| **edit** | `edit [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g., `edit 1 p/91234567 e/johndoe@example.com` | +| **find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` | +| **exit** | `exit` | From 4fc9facdd9c3c3e58094f827aea61f0bd8bb24a6 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 6 Apr 2022 21:39:03 +0800 Subject: [PATCH 090/140] Update findt to fix bug and update user guide --- docs/UserGuide.md | 4 +++- src/main/java/seedu/address/model/TaskList.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4bf2dd9fff8..6b344e5def8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -127,8 +127,10 @@ Format: `findt KEYWORD [MORE_KEYWORDS]` - The order of the keywords matters. e.g. `drink water` will not match `water drink` - Only full keyword(s) will be accepted. e.g. `drink` will match `drink`; `ink` will not match `drink` - All keyword(s) have to be matched for task to be returned. +- If a word is contained within a parantheses without spaces, the keyword has to contain the parantheses as well. +e.g. `Assignment` will not match `(Assignment`. -Example: `findt lessons` returns `Swimming lessons 03/05/2022`. +Example: `findt lessons` returns `Swimming lessons 03/05/2022`. ### Feature 5 #### Feature - List all tasks: `viewt` diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 3277e06e875..bc9d44d7b4c 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -109,7 +109,7 @@ public String findTask(String input) { ArrayList matchingTasks = new ArrayList<>(); for (int i = 0; i < this.taskList.size(); i++) { Task curr = this.taskList.get(i); - String pattern = "(?i)(? Date: Wed, 6 Apr 2022 21:45:18 +0800 Subject: [PATCH 091/140] fix checkstyle error and add credit --- src/main/java/seedu/address/model/TaskList.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index bc9d44d7b4c..3e9b23541f9 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -109,7 +109,10 @@ public String findTask(String input) { ArrayList matchingTasks = new ArrayList<>(); for (int i = 0; i < this.taskList.size(); i++) { Task curr = this.taskList.get(i); - String pattern = "(?i)(?<=|^|\\.)" + Pattern.quote(input) + "(?=\\s|$|\\.)"; //bypass case sensitivity with regex + // Solution below adapted from + // https://stackoverflow.com/questions/25483114/regex-to-find-whole-word-in-text-but-case-insensitive + String pattern = "(?i)(?<=|^|\\.)" + + Pattern.quote(input) + "(?=\\s|$|\\.)"; //bypass case sensitivity with regex if (Pattern.compile(pattern).matcher(curr.toString()).find()) { matchingTasks.add(curr); } From 66ee9ad98baf556f3be77156c049c830b831c4cf Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Thu, 7 Apr 2022 00:32:34 +0800 Subject: [PATCH 092/140] Update AddTaskCommandParser Logic - Add method to check if user's deadline input is before today's date - Add method to check if user's deadline input is a valid date - Add method to check if user's description input contains deadline prefix - Add necessary tests to test the new methods --- .../logic/parser/AddTaskCommandParser.java | 95 ++++++++++++++++--- .../parser/AddTaskCommandParserTest.java | 50 +++++++--- 2 files changed, 117 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java index 0501f592c2a..d54af9ed2c5 100644 --- a/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddTaskCommandParser.java @@ -1,10 +1,12 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.List; @@ -26,18 +28,23 @@ public AddTaskCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, PREFIX_ADD_TASK_DEADLINE); - try { - // Throw exception if more than 1 description or deadline prefix exists - checkMultiplePrefixTokens(argMultimap); + // Throw exception if more than 1 description or deadline prefix exists + checkMultiplePrefixTokens(argMultimap); - // Throw exception if user input does not contain any description prefix - checkDescriptionPrefixEmpty(argMultimap); + // Throw exception if user input does not contain any description prefix + checkDescriptionPrefixEmpty(argMultimap); - // Throw exception if deadline does not adhere to specified format - checkDeadlineFormat(argMultimap); - } catch (ParseException e) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); - } + // Throw exception if deadline does not adhere to specified format + checkDeadlineFormat(argMultimap); + + // Throw exception if deadline is invalid + checkDeadlineValidity(argMultimap); + + // Throw exception if deadline is before today's date + checkDeadlineIsBeforeToday(argMultimap); + + // Throw exception if description contains deadline prefix + checkDeadlinePrefixInDescription(argMultimap); String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); @@ -64,7 +71,7 @@ private void checkMultiplePrefixTokens(ArgumentMultimap argMultimap) throws Pars // Throw exception if more than 1 description or deadline token is used if (description.size() > 1 || deadline.size() > 1) { // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + throw new ParseException("Duplicated prefix detected in input!\n" + AddTaskCommand.MESSAGE_USAGE); } } @@ -77,7 +84,7 @@ private void checkMultiplePrefixTokens(ArgumentMultimap argMultimap) throws Pars private void checkDescriptionPrefixEmpty(ArgumentMultimap argMultimap) throws ParseException { String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); if (description.equals("")) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + throw new ParseException("Description is compulsory!\n" + AddTaskCommand.MESSAGE_USAGE); } } @@ -99,7 +106,67 @@ private void checkDeadlineFormat(ArgumentMultimap argMultimap) throws ParseExcep try { dateTimeFormatter.parse(deadline); } catch (DateTimeParseException e) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + throw new ParseException("Deadline is not in dd/mm/yyyy!\n" + AddTaskCommand.MESSAGE_USAGE); + } + } + + /** + * Check if user's deadline is a valid date. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if deadline is not a valid date + */ + private void checkDeadlineValidity(ArgumentMultimap argMultimap) throws ParseException { + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy"); + + if (deadline.equals("")) { + return; + } + + try { + // Check if user's deadline input is a valid date + simpleDateFormat.setLenient(false); + simpleDateFormat.parse(deadline); + } catch (java.text.ParseException e) { + throw new ParseException("Invalid date input!\n" + AddTaskCommand.MESSAGE_USAGE); + } + } + + /** + * Check if user's deadline is before today's date. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if deadline is before today's date + */ + private void checkDeadlineIsBeforeToday(ArgumentMultimap argMultimap) throws ParseException { + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + + if (deadline.equals("")) { + return; + } + + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate date = LocalDate.parse(deadline, dateTimeFormatter); + if (date.isBefore(today)) { + throw new ParseException("Deadline is before today's date!\n" + AddTaskCommand.MESSAGE_USAGE); + } + } + + /** + * Check if user's description contains deadline prefix. + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if description contains deadline prefix + */ + private void checkDeadlinePrefixInDescription(ArgumentMultimap argMultimap) throws ParseException { + String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); + + if (description.contains("t/")) { + // if deadline token is used in the description + throw new ParseException("You cannot have 't/' prefix in the description!\n" + + AddTaskCommand.MESSAGE_USAGE); } } } diff --git a/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java index ede00c260b4..8d4ea59615d 100644 --- a/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddTaskCommandParserTest.java @@ -1,6 +1,5 @@ package seedu.address.logic.parser; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; @@ -13,8 +12,8 @@ public class AddTaskCommandParserTest { @Test public void parse_allFieldPresent_success() { - assertParseSuccess(parser, "addt d/description t/01/01/2022", - new AddTaskCommand("description", "01/01/2022")); + assertParseSuccess(parser, "addt d/description t/01/01/2222", + new AddTaskCommand("description", "01/01/2222")); } @Test @@ -25,19 +24,19 @@ public void parse_optionalFieldsMissing_success() { @Test public void parse_multipleDescriptions_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + String expectedMessage = "Duplicated prefix detected in input!\n" + AddTaskCommand.MESSAGE_USAGE; assertParseFailure(parser, "addt d/abc d/abc", expectedMessage); } @Test public void parse_multipleDeadline_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); - assertParseFailure(parser, "addt d/abc t/01/01/2022 t/01/01/2022", expectedMessage); + String expectedMessage = "Duplicated prefix detected in input!\n" + AddTaskCommand.MESSAGE_USAGE; + assertParseFailure(parser, "addt d/abc t/01/01/2222 t/01/01/2222", expectedMessage); } @Test public void parse_compulsoryFieldMissing_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + String expectedMessage = "Description is compulsory!\n" + AddTaskCommand.MESSAGE_USAGE; // has description prefix assertParseFailure(parser, "addt d/", expectedMessage); @@ -51,24 +50,24 @@ public void parse_compulsoryFieldMissing_failure() { @Test public void parse_deadlineFormat_success() { - assertParseSuccess(parser, "addt d/description t/01/01/2022", - new AddTaskCommand("description", "01/01/2022")); + assertParseSuccess(parser, "addt d/description t/01/01/2222", + new AddTaskCommand("description", "01/01/2222")); } @Test public void parse_deadlineFormat_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + String expectedMessage = "Deadline is not in dd/mm/yyyy!\n" + AddTaskCommand.MESSAGE_USAGE; // no "/" between date, month, year - assertParseFailure(parser, "addt d/description t/01012022", expectedMessage); + assertParseFailure(parser, "addt d/description t/01012222", expectedMessage); // uses "-" between date, month, year - assertParseFailure(parser, "addt d/description t/01-01-2022", expectedMessage); + assertParseFailure(parser, "addt d/description t/01-01-2222", expectedMessage); } @Test public void parse_deadlineFormatUseAlphabets_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + String expectedMessage = "Deadline is not in dd/mm/yyyy!\n" + AddTaskCommand.MESSAGE_USAGE; assertParseFailure(parser, "addt d/description t/monday", expectedMessage); assertParseFailure(parser, "addt d/description t/o1/o1/2o22", expectedMessage); @@ -76,9 +75,32 @@ public void parse_deadlineFormatUseAlphabets_failure() { @Test public void parse_deadlineFormatUseSymbols_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE); + String expectedMessage = "Deadline is not in dd/mm/yyyy!\n" + AddTaskCommand.MESSAGE_USAGE; assertParseFailure(parser, "addt d/description t/!@#$%^&*(){}[]|~`", expectedMessage); assertParseFailure(parser, "addt d/description t/*10!2()22", expectedMessage); } + + @Test + public void parse_deadlineFormatIsBeforeTodayDate_failure() { + String expectedMessage = "Deadline is before today's date!\n" + AddTaskCommand.MESSAGE_USAGE; + + assertParseFailure(parser, "addt d/description t/01/01/2022", expectedMessage); + } + + @Test + public void parse_descriptionContainsDeadlinePrefix_failure() { + String expectedMessage = "You cannot have 't/' prefix in the description!\n" + AddTaskCommand.MESSAGE_USAGE; + + assertParseFailure(parser, "addt d/descriptiont/01/02/2022 t/01/01/2222", expectedMessage); + } + + @Test + public void parse_descriptionValidity_failure() { + String expectedMessage = "Invalid date input!\n" + AddTaskCommand.MESSAGE_USAGE; + + assertParseFailure(parser, "addt d/description t/31/02/2022", expectedMessage); + assertParseFailure(parser, "addt d/description t/30/02/2022", expectedMessage); + assertParseFailure(parser, "addt d/description t/29/02/2022", expectedMessage); + } } From d1f1e1929cc78ac9eb2d08f31f75413c08d62225 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 7 Apr 2022 23:27:25 +0800 Subject: [PATCH 093/140] Update GUI and fix GUI bug --- src/main/java/seedu/address/ui/TaskCard.java | 1 - src/main/resources/images/contact.png | Bin 0 -> 2135 bytes src/main/resources/images/task.png | Bin 0 -> 1984 bytes src/main/resources/view/MainWindow.fxml | 23 ++++++++++++++++++ src/main/resources/view/ThemePresets.css | 24 +++++++++++++------ 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/images/contact.png create mode 100644 src/main/resources/images/task.png diff --git a/src/main/java/seedu/address/ui/TaskCard.java b/src/main/java/seedu/address/ui/TaskCard.java index 76e5f1f8998..1374c4de3c8 100644 --- a/src/main/java/seedu/address/ui/TaskCard.java +++ b/src/main/java/seedu/address/ui/TaskCard.java @@ -35,7 +35,6 @@ public TaskCard(Task task, int displayedIndex) { super(FXML); this.task = task; taskId.setText(displayedIndex + ". "); - //taskTitle.setText("Tasks:"); taskDescription.setText(task.getDescription()); taskDeadline.setText(task.getDeadline()); } diff --git a/src/main/resources/images/contact.png b/src/main/resources/images/contact.png new file mode 100644 index 0000000000000000000000000000000000000000..2b8eef3892abb0e1d362bc40b087c2cf0cc6d03b GIT binary patch literal 2135 zcmV-d2&ngoP)dm>2qBbr0t5(;;6NUbmt(LU zzxKzq-3I$-$MAEKLB7(}?{UvPzjMy@?|y&x+-n#?R8#=R04LxZrp4*EaY;O!A8O}f zEz4qYP!Xm6OQ3Yq+I-gjC=abhiNd@efE{aMc}#ra_QEIi@cs!v{1Rpkw5>8qeK8Pp zez-!dgo??*%aT~yM)OJw3~T2D(5Ql^x>(u`f6w9!sQ^?X1{44k=KYkdJU%!U$%DXv zXaN>S5|j#n_x>A-Xv5|3#8}|Zkp$Ed_sjf8AAs-DvohKge+2CHGgfXS*^x0|s0|ou zj08a9{{J-#D9rnVU#!5@NV1PQ3q-}^zyeQ2l6~yQ0I6Sq?C^Nu^i8O5flKYsaTjb( zQJ16xqaMteP-KFV98e8X*Tg*lc9)o{?!O4#_V6;D_e8mT8+Mai!>Ti&3YVP$s4T;I;SQ?z)Au zxen*G<8mVtF_op?!wi61)s|SfI^diHY*?f)TJamH62~v)9CU_xO?hTtkwTu?*%tjC;W6i zCkd9CrJk{&yv?(Sp!ge9sb<_3bhVn<*)iV@3>lv?f6dAN_g=Zm_HuU zMv1x}2OMmK?I*zY<%eiZ6G<2+#v84v0AuAZ>G=59?7PrMkqKrzA)n2%y;XJ>Y^@RJ z$@6}IHfK`5dfUlefN*|k(O1p`q$G$D|9j7f>$|6R^=qrmnN0HB)c|Zg0uGm4R?9dS z*n1wV4$$UILSG!3gmJZB0YuM-gWV;Pn*e=njUn~=k|k)z6w>2>y%!>y64P8j78dY$ zVb6JSZkV+)tZ-n!Q>(zzC3wHv4$a-rcn2=GL!ZYl+jlSYAqoYCSu5$-`8s>fLFE*A zSV0yRsBaOyuQukP8(S1n_T}y2@2iwb=1ntm_(X$bTU~Au>hxTCIxU=Qh2k;chv4{KC7vhl-YOaj9-s*9y9Qan?12w86L8*fWz%qrVZb-0Eva=0IdK0dvx{O z4XN+w?q%)fcK{ew_)SSY3a#Kzr(05F@H0a0fV4__>NaZ9LbTZvxOnXrC6&M6gS|Ca zZFa0SJ3IE&@O0%mnp->2W)}p56%GoOcxyc&7CsncVS&^{F~9fPI#H!$g_TjL)TC8x zpzG7kSXwTz;%8ezWVG1@q*bgBIvEZgTL%Cs(m%Gr&j^jyi=*4x7Ew;6Psg}?lVrVd z`9@Uww1_%9{%08VvDqjESy;fF2^ZVJX*r87w>YHU(|a3NTO)n#SAt)J0KQ8*0D{!l z`N>8!nd8xBjz^P~kIIk{qRVMH3&4cXst1BB0hnSESs%xhTK`NA+}$no9(fn1Lf3o!w7< z;lgLp>y!BCqYnXCzWlqaTlX4jwVFkXo)5~kw6w5c!+H)J_%FRR@8Rxl1>m^?`LaXN z@+%=MAhk!x?t-816q6jG)<;cEEhbZht{MPZT5d6W_N<^zqaL<=Cw#JW#ozr#_h*5C zL17_VJ|Iye5}1Ay03O_}ckdpsQHKv7X4$ezHg5baUXO>RMeyo^fn|gP_6}-BC`1;K_ZyQU7DgHx zF7V1LKjE#nCQx3!kg~G*3S>m@YlZ zd}zqV0#a~!U|$3Ls}6c3md5T!N}>qhqKW6uw|MPThJe+^z@jpAmXIew2irxSK N002ovPDHLkV1ndp2}1w? literal 0 HcmV?d00001 diff --git a/src/main/resources/images/task.png b/src/main/resources/images/task.png new file mode 100644 index 0000000000000000000000000000000000000000..d85bc9e7ab4fd7a1b4630eaf89ccb0f7793c515a GIT binary patch literal 1984 zcmV;x2S50UP)VqwNeb zjymFxYMp7PPCL$2OOXyZh_wb9+s=q6qa9}o&gfWeopzLB14S)h!;di#6GB2r780^a zHrZ^l*=+XhyZ#Y~lj(bJce5{>ANBLk?!0r~IVa!j-h0ovZzX^&mD^55BIF#ni-- zg`oh|KR%4t>yPS001tk4tywuG6+;1(u);&dxqN+DzNURxQF*+k2_>vdNpi`+PyhhC zERk-PHEoh4nVwKg2w_^_Svd*HvSb_h=e{R}2|~b~st z&&5?JL=~XH8{kl*N7EKoRn6$>ZzYY8{mhrQ888k$& zx99zRi((l%HwA!9E7HDL2F_Ihkl?G{_xF}X8#iYK04!E4+oKLjMkdpRfUW)yev)f6 zW=;zL*wwK7C8Gg`%iy3tfTye9ID*|uVR6AEa!VG{mw|(NRzm@v{m#$m=;)0aV*9Q~ zxc^gk$DdnrsOUOcomTLfX9HSBLji^chgrWclZT46E6z|v<%L=|LxaO6weFkd;1B1?U(Gak6tj(-w++comQ&iTr|u8nxp@oH4h=qM_T-F%%#( zE1k3MZq9o2J3;`N^R$=A8G}IkKS&e-Ui$gd3=9kz`nFnS=I3QiGP4iU*XO6J)63{+ znBJiXL!%QvWqsX!s6tTR8q)PKFHL4~zKmu3WCx#$ur;^V*ks3 zp!ReFB8K^6?`y_2N_M);BM)b?w#-ks`-; z>ZJ^iFy!e+Am|CJ92-#B|GJN-_7QwMSgaF$WLd|)Mv7#ar+ZJrQD+E>5FEeeBOK@cYt9I8pss@h z^<8+C_)2ucN$^KIU!}4Bs-XkfDzjtvH(61xTX0P|Z?yDs-0kDhW%(2+nvEY_3+mM7hr76joKyM@<(cZ_%*5o&F@ zPLV_VBm9Ls^T=?>9IWeP&%fGn<)m`rx{t?JEac-0bQ?V}W4Zt~n-$q&Au@>xNsr3H z9J1|Js?S}g-Wy<3VK$pf43GR`CaM6V5y8-?c2{OtW7FX(E9Qq)kH?k7?j64(+y#;DK#CZGmW@*@fypl0E7S~B8{6<$6g);5UL>L?-N3aY~TFpXFl=vv6s#yRe-wl z&77@mWZhRjPx0!NQx+#M4DL?tjYuRkBDK8vsy*cQRRNolx)pA3>jI$g?iEuS$7%5M zCE1Ze#*&XAS)^5vN$O|w&2{vDH^T*#GpVDCU z7sgJgE}b}u35UnJ2%y(s^BU~#7=M3DfX4a@t?O?kIMvksr6wtHjF4ox5#YaH + + + @@ -38,6 +41,16 @@ + + + + + + @@ -45,6 +58,16 @@ + + + + + + diff --git a/src/main/resources/view/ThemePresets.css b/src/main/resources/view/ThemePresets.css index fd914a83824..45e1a6570a8 100644 --- a/src/main/resources/view/ThemePresets.css +++ b/src/main/resources/view/ThemePresets.css @@ -1,3 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Basic&display=swap'); + .background { -fx-background-color: derive(#fffff0, 20%); background-color: #383838; /* Used in the default.html file */ @@ -86,6 +88,17 @@ -fx-background-color: derive(#f0ffff, 20%); } +.header-icons { + -fx-background-color: derive(#f0ffff, 20%); +} + +.icon-text { + -fx-font-size: 22pt; + -fx-font-family: 'Basic', sans-serif; + -fx-text-fill: black; + -fx-opacity: 1; +} + .list-view { -fx-background-insets: 0; -fx-padding: 0; @@ -96,15 +109,18 @@ -fx-label-padding: 0 0 0 0; -fx-graphic-text-gap : 0; -fx-background-insets: 3px; - -fx-background-radius: 15; + -fx-background-color: derive(#f0ffff, 20%); + } .list-cell:filled:even { -fx-background-color: #e8eaf6; + -fx-background-radius: 15; } .list-cell:filled:odd { -fx-background-color: #dadef1; + -fx-background-radius: 15; } .list-cell:filled:selected { @@ -113,7 +129,6 @@ .list-cell:filled:selected #cardPane { -fx-label-padding: 0 0 0 0; - -fx-border-color: #3e7b91; -fx-border-width: 1; -fx-background-insets: 3px; -fx-border-radius: 15; @@ -211,11 +226,6 @@ -fx-background-color: #c9f1fd; } -.menu-item .label{ - -fx-background-color: #c9f1fd; - -fx-text-fill: black; -} - .context-menu { -fx-background-color: #c9f1fd; -fx-border-color: #1d1d1d; From 777e1f12530bcbe1d5b8e73e102303962e9e3dd8 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 7 Apr 2022 23:29:29 +0800 Subject: [PATCH 094/140] update GUI --- src/main/resources/view/ThemePresets.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/view/ThemePresets.css b/src/main/resources/view/ThemePresets.css index 45e1a6570a8..c1009935934 100644 --- a/src/main/resources/view/ThemePresets.css +++ b/src/main/resources/view/ThemePresets.css @@ -93,6 +93,7 @@ } .icon-text { + -fx-background-color: derive(#f0ffff, 20%); -fx-font-size: 22pt; -fx-font-family: 'Basic', sans-serif; -fx-text-fill: black; From f3a61a432ab2f93cb8dfeae96606d5c119081279 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 7 Apr 2022 23:36:32 +0800 Subject: [PATCH 095/140] allow wrap text --- src/main/resources/view/PersonListCard.fxml | 6 +++--- src/main/resources/view/TaskCard.fxml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index f08ea32ad55..2e0a4e8b0e9 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -28,9 +28,9 @@
-

51b=yqV8vs1H$ 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 literal 0 HcmV?d00001 From 0dda652620a5e3b806a3d6f3766045f582e06e1f Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Thu, 24 Mar 2022 22:12:13 +0800 Subject: [PATCH 057/140] Fix checkstyle errors --- docs/AboutUs.md | 3 --- docs/DeveloperGuide.md | 2 +- docs/diagrams/DeleteTaskActivityDiagram.puml | 2 +- docs/team/ivorcmx.md | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 953beefc1ad..7653de14518 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -17,7 +17,6 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/putaojuice.md)] * Role: Team Lead -* ### Low Weimin, Ian @@ -35,7 +34,6 @@ You can reach us at the email `e0544443@u.nus.edu` [[github](http://github.com/ivorcmx)] [[portfolio](team/ivorcmx.md)] - * Role: Testing * @@ -47,4 +45,3 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/yumengtan.md)] * Role: Code Quality -* diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 55cefb375ce..c4f7901f47c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -463,7 +463,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli 2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. 3. 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. 4. The command used should be simple to learn. -5. The system should be usable by a novice who has never used the system before. +5. The system should be usable by a novice who has never used the system before. 6. The system should be backward compatible with data produced by earlier versions of the system. 7. Each command should not take more than 2 second to complete and display the result. 8. Texts in the UI should wrap around. diff --git a/docs/diagrams/DeleteTaskActivityDiagram.puml b/docs/diagrams/DeleteTaskActivityDiagram.puml index a40907106a2..4b5d2a56fc4 100644 --- a/docs/diagrams/DeleteTaskActivityDiagram.puml +++ b/docs/diagrams/DeleteTaskActivityDiagram.puml @@ -15,4 +15,4 @@ else ([Invalid Format Used]) -Prompt user with the command's format endif stop -@enduml \ No newline at end of file +@enduml diff --git a/docs/team/ivorcmx.md b/docs/team/ivorcmx.md index ce9b0ecc1cc..6a882851912 100644 --- a/docs/team/ivorcmx.md +++ b/docs/team/ivorcmx.md @@ -19,6 +19,7 @@ Given below are my contributions to the project. * `DeleteTaskCommandTest` * **Additional info**: * Updated ParserUtil method of parseNumber to work with DeleteTaskCommand + * Added relevant activity and sequence diagrams into Developer Guide * **New Feature**: * to be added soon @@ -40,6 +41,8 @@ Given below are my contributions to the project. * Contribute to glossary in the developer guide. * Added user story for Delete task feature. * Added MSS for `DeleteTask`. + * Add sequence diagram for delete task + * Add activity diagram for delete task * **Community**: * to be added soon From ffab83f50d33f25a5875ef27edf4c2ec3f8c2b00 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 24 Mar 2022 23:19:50 +0800 Subject: [PATCH 058/140] Edit Checkstyle --- README.md | 6 ++---- docs/DeveloperGuide.md | 1 - docs/diagrams/FindTaskActivityDiagram.puml | 2 +- docs/diagrams/FindTaskSequenceDiagram.puml | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f1cd21b53e3..b0834b28bb8 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ ![Ui](docs/images/Ui.png) # NUScheduler -*** - +*** NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps.
@@ -14,7 +13,6 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona *** * keep track of all school contacts, modules and tasks * organise academic life in a neat manner - ## Features: *** @@ -25,7 +23,7 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona * View all tasks and their deadlines * View all contacts * Remind upcoming tasks - + * ## Acknowledgements *** This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative.](https://se-education.org) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index bd5aceee9de..9c9bb396a51 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -289,7 +289,6 @@ The following sequence diagram shows how the add task operation work assuming no ![FindTaskCommandSequenceDiagram](images/FindTaskSequenceDiagram.png) - _{more aspects and alternatives to be added}_ -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/diagrams/FindTaskActivityDiagram.puml b/docs/diagrams/FindTaskActivityDiagram.puml index 2a04ca217ae..111d8a6b500 100644 --- a/docs/diagrams/FindTaskActivityDiagram.puml +++ b/docs/diagrams/FindTaskActivityDiagram.puml @@ -30,4 +30,4 @@ skinparam activity { endif stop -@enduml \ No newline at end of file +@enduml diff --git a/docs/diagrams/FindTaskSequenceDiagram.puml b/docs/diagrams/FindTaskSequenceDiagram.puml index bbc49ced057..2c3fae9fb4c 100644 --- a/docs/diagrams/FindTaskSequenceDiagram.puml +++ b/docs/diagrams/FindTaskSequenceDiagram.puml @@ -60,4 +60,4 @@ deactivate FindTaskCommand [<--LogicManager deactivate LogicManager -@enduml \ No newline at end of file +@enduml From d3b5f947d669e26d69c315c4c2bf26fba28eff6d Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 24 Mar 2022 23:43:36 +0800 Subject: [PATCH 059/140] Configure layout of Ui and badges --- README.md | 1 + docs/index.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index f1cd21b53e3..111c7e44cf6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![CI Status](https://github.com/AY2122S2-CS2103-F11-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) [![codecov](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp/branch/master/graph/badge.svg?token=G5ITTT4UTJ)](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp) + ![Ui](docs/images/Ui.png) # NUScheduler diff --git a/docs/index.md b/docs/index.md index 3342c15f51c..d5addeb9095 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,6 +5,7 @@ title: NUScheduler [![CI Status](https://github.com/AY2122S2-CS2103-F11-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S2-CS2103-F11-4/tp/actions) [![codecov](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp/branch/master/graph/badge.svg?token=G5ITTT4UTJ)](https://codecov.io/gh/AY2122S2-CS2103-F11-4/tp) + ![Ui](images/Ui.png) **NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts**, From 7fdacd2a0c453bd7f3f94dfd33c24cf3986ea0b4 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Fri, 25 Mar 2022 00:32:43 +0800 Subject: [PATCH 060/140] refactor: Update Icon and title --- src/main/java/seedu/address/MainApp.java | 8 +++---- .../java/seedu/address/ui/HelpWindow.java | 2 +- src/main/java/seedu/address/ui/UiManager.java | 2 +- src/main/resources/images/NUScheduler_32.png | Bin 0 -> 1887 bytes src/main/resources/view/MainWindow.fxml | 20 ++++++++---------- 5 files changed, 15 insertions(+), 17 deletions(-) create mode 100644 src/main/resources/images/NUScheduler_32.png diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 8c81ba20092..6dd82cd8a30 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -48,7 +48,7 @@ public class MainApp extends Application { @Override public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); + logger.info("=============================[ Initializing NUScheduler ]==========================="); super.init(); AppParameters appParameters = AppParameters.parse(getParameters()); @@ -151,7 +151,7 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { + "Using default user prefs"); initializedPrefs = new UserPrefs(); } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); + logger.warning("Problem while reading from the file. Will be starting with an empty NUScheduler"); initializedPrefs = new UserPrefs(); } @@ -167,13 +167,13 @@ protected UserPrefs initPrefs(UserPrefsStorage storage) { @Override public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); + logger.info("Starting NUScheduler " + MainApp.VERSION); ui.start(primaryStage); } @Override public void stop() { - logger.info("============================ [ Stopping Address Book ] ============================="); + logger.info("============================ [ Stopping NUScheduler ] ============================="); try { storage.saveUserPrefs(model.getUserPrefs()); } catch (IOException e) { diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/address/ui/HelpWindow.java index 9a665915949..aa3bc774d42 100644 --- a/src/main/java/seedu/address/ui/HelpWindow.java +++ b/src/main/java/seedu/address/ui/HelpWindow.java @@ -15,7 +15,7 @@ */ public class HelpWindow extends UiPart { - public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html"; + public static final String USERGUIDE_URL = "https://ay2122s2-cs2103-f11-4.github.io/tp/UserGuide.html"; public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL; private static final Logger logger = LogsCenter.getLogger(HelpWindow.class); diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index fdf024138bc..fd413ea84b1 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -20,7 +20,7 @@ public class UiManager implements Ui { public static final String ALERT_DIALOG_PANE_FIELD_ID = "alertDialogPane"; private static final Logger logger = LogsCenter.getLogger(UiManager.class); - private static final String ICON_APPLICATION = "/images/address_book_32.png"; + private static final String ICON_APPLICATION = "/images/NUScheduler_32.png"; private Logic logic; private MainWindow mainWindow; diff --git a/src/main/resources/images/NUScheduler_32.png b/src/main/resources/images/NUScheduler_32.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe78bff48a172e27e0726a8d4630fc9d34dc6f4 GIT binary patch literal 1887 zcmZ{lc{tRGAIHCLhH))sVh!bLTF2z52n``4GlX))n%pBY?wA~vaYQxiN~|?z8&_?{ z5#=^4nwXh{b=R7V$PtY*w9}uzKYq{WdB5M!^L{_Czdu>dmg`es_ zBreML=)^=GKZJv=&{hCY_fT^Gn#hmQ-`)ic0EyZFkeUVnd;BW(69B{_0AL9V0A@u1 z0Kxy>a><-Oi27Z;U;}*rapd;OJbojAxA%+&0O_6|66lYp3gDMwF(|aH7*_}?b5?v| zJ-&($Vo)|#ZXP|Qk0v4lE-3b;T;AUD*=r)KkNp~yqtjdLNYMoe;}kLlBrdMMwOG2F97=u;xc`Yw-p!3?X}llb-7}lk}*jmbuG}?{MjZ z_MFjBMW)CkPO+!%?g-aI^985G;z4(=I=6slr9ueLaHIEuxl_h!)?ek)#7H{iFi)gs zszBcB*gVOi4@!<5qVtgMs6!_}o5&HPb%O2+(Jb&a&P60tfk=oz>TPpkn0hLwFctp( z_A50cZZSoe#KW%D;&((s#O}r78Dvo9Cp)yxcD*>oA8OpSfjv|$+GWb}&_J$q*moFa zth*$At}PX7UgOP0%Oswqm+i)5S66;f*B2TPrEQ)K`RhClm|e!ZL*6@Mb8cZ$eB;%S z*X=bvSrm-u9*Qq*8w@32F6Z?$us#Ho);j4*$4xq30lU61JU|GNu~W+?4?KS_p?FE0 zxe-^DpY7o#B&!1-%G2L`d;(Wk*BafmLd3b@RR)!ola7tLv=hLoTcSVjt4^ONvltJE z4KH=~^$O~+%vv*TJS*f?3cGupyRg4yxE6;};q?0ff;&-*U zhjXf9ZFohxsMbl|?xfBN%qTBV`GOudD6|*FxW2vmW%a-vPuDxT$;kNN=B&*EU+q+^ ztDdDoloJm~2nT4IT*sPU)cJ-{Eh&wPr&?w+0@SWx%EyN06vuMxpD!p^9+O8^W%F<4 zo}rE|UV55O)0KQ5UGzr{@}}@i_|Dij#HJY|4c)`>b$E=PHVxjGXckb=&N7{zuu@EF z96L`@84($)L|MO$T)$@<#u5rIeN=1p#~Xk6`qD+(zH1mgeIz+@)!QEPCS*r-v&9%@ ziF6vP>f9BLY$jBXOuI+~dTJh6{+rS?k;ID#a=-G0G5<8MMiMKA7|&>YI7B|G6|$?* zi+($i;4q7uGZ=YIDPqnV)t{k%6b+xshbYmKoG7yWJQY?Zmn+;=P)_yj)w7=r$$hYV z%Wd0`taqQ&($gubBhD@~FRO$P4WThjO(#9=3N;nNK9_97nt&2OD47!DeDA04`V2z{ zEQr={;;?c!IB>L{-IP>;Z*oO0E+E-WHWrd~#N*yWqvBGG;qi`)lj-KLJpn4s$6ef% ziLj%ckW_gCG1fk(^Y6eWxaqSW1cVqgb;#lpV2kPj&ngOZC=cS~?w>YogFY04se_KP zjnLWeW?73~;ZUhf=^q(dPxy7HjZ+Ux{eE^4tTD zrzPpR%nT0FS+G;wQ(v8lwCtw^ls6s>%X{c6zq!lECT(V1f}%C6fv&IW=)mo3YWdct z`ecOYDMC7;^~MQ}peqw|5II+!`VcWcGqh#YuK7h2on(wcy|4|Hf)~5NU%^19bpu}( z=6GthWBpK4GL^|)Wr~p2P7qV#WuCh>0=m&7^x)j?4xRZVRDnc2Qaz7I_(Qj zt>Ow@&jgGjvY?S~NrTBUW-9FWa@CEu5*8Z`aM|WkN2O}RbXn09sUY8^(qW!4)eB7B z3=GdImW9!ICC-Oi3ElNrh)Su=J>GW!~W9NTtZ-8Sy z5oNlna{vIpBXe_4?6)^qiREKCaQr_txDkcQ`776UgM(kGfdQclzVvtJviuYmy8kLI zyVIxakQUA+IU!`4-`~ZqFXd@C*{y)b4}`eR$njT@M;@&0I%EvL{%W0CQ^pfEI&K~W>ha~hNmCGGvc9%?CK z_UJ0@I7Z!J??*i@Q46h XP{RKQ4yuY6d;mb%Vr-sUWAFS2uZUuY literal 0 HcmV?d00001 diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index a431648f6c0..4aaf95de2a7 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -6,13 +6,12 @@ - + - + @@ -33,24 +32,23 @@ - + - + - + - + - + - + - + From e216f04caab38302c4ebda0d362074c1b00022f4 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Sat, 26 Mar 2022 18:46:53 +0800 Subject: [PATCH 061/140] Add update task command and its parser --- .../logic/commands/UpdateTaskCommand.java | 171 ++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 + .../logic/parser/UpdateTaskCommandParser.java | 142 +++++++++++++++ src/main/java/seedu/address/model/Model.java | 2 + .../seedu/address/model/ModelManager.java | 7 + .../java/seedu/address/model/TaskList.java | 9 + .../java/seedu/address/model/task/Task.java | 69 ++++++- .../logic/commands/AddCommandTest.java | 5 + .../logic/commands/AddTaskCommandTest.java | 5 + .../logic/commands/DeleteTaskCommandTest.java | 5 + .../logic/commands/FindTaskCommandTest.java | 5 + .../logic/commands/ViewTaskCommandTest.java | 5 + 12 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java new file mode 100644 index 00000000000..4cc166fca04 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -0,0 +1,171 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.TaskList; +import seedu.address.model.task.Task; + +public class UpdateTaskCommand extends Command { + public static final String COMMAND_WORD = "updt"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Updates the details of the chosen task" + + " by the task ID used in the displayed task list. " + + "Existing values will be overwritten by the input values.\n" + + "At least one field must be updated " + + "Parameters: Task ID (must be a positive integer) " + + "[" + PREFIX_ADD_TASK_DESCRIPTION + "DESCRIPTION] " + + "[" + PREFIX_ADD_TASK_DEADLINE + "DEADLINE]...\n" + + "Example: " + COMMAND_WORD + " 1 " + + PREFIX_ADD_TASK_DESCRIPTION + "Running Lesson " + + PREFIX_ADD_TASK_DEADLINE + "04/05/2022"; + + public static final String MESSAGE_UPDATE_TASK_SUCCESS = "Updated Task: %1$s"; + public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; + public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task list."; + public static final String MESSAGE_INVALID_TASK_DISPLAYED_ID = "The task id provided is invalid"; + + private final Integer taskId; + private final UpdateTaskDescriptor updateTaskDescriptor; + + /** + * @param taskId of the person in the filtered person list to edit + * @param updateTaskDescriptor details to edit the person with + */ + public UpdateTaskCommand(Integer taskId, UpdateTaskDescriptor updateTaskDescriptor) { + requireNonNull(taskId); + requireNonNull(updateTaskDescriptor); + + this.taskId = taskId; + this.updateTaskDescriptor = new UpdateTaskDescriptor(updateTaskDescriptor); + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + TaskList lastShownList = model.getTaskList(); + + if (taskId > lastShownList.size()) { + throw new CommandException(MESSAGE_INVALID_TASK_DISPLAYED_ID); + } + + Task taskToUpdate = lastShownList.getTask(taskId); + Task updatedTask = createUpdatedTask(taskToUpdate, updateTaskDescriptor); + + if (taskToUpdate.equals(updatedTask)) { + throw new CommandException(MESSAGE_DUPLICATE_TASK); + } + + model.updateTask(taskToUpdate, updatedTask); + + return new CommandResult(String.format(MESSAGE_UPDATE_TASK_SUCCESS, updatedTask)); + } + + /** + * Creates and returns a {@code Task} with the details of {@code taskToEdit} + * edited with {@code updateTaskDescriptor}. + */ + private static Task createUpdatedTask(Task taskToUpdate, UpdateTaskDescriptor updateTaskDescriptor) { + assert taskToUpdate != null; + + String updatedDescription = ""; + String updatedDeadline = ""; + + if (updateTaskDescriptor.getDescription() == null) { + updatedDescription = taskToUpdate.getDescription(); + } else { + updatedDescription = updateTaskDescriptor.getDescription(); + } + + if (updateTaskDescriptor.getDeadline() == null) { + updatedDeadline = taskToUpdate.getDeadline(); + } else { + updatedDeadline = updateTaskDescriptor.getDeadline(); + } + + if (updatedDeadline == null) { + return new Task(updatedDescription, "No deadline set"); + } else { + return new Task(updatedDescription, updatedDeadline); + } + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof UpdateTaskCommand)) { + return false; + } + + // state check + UpdateTaskCommand e = (UpdateTaskCommand) other; + return taskId.equals(e.taskId) + && updateTaskDescriptor.equals(e.updateTaskDescriptor); + } + + /** + * Stores the details to edit the task with. Each non-empty field value will replace the + * corresponding field value of the task. + */ + public static class UpdateTaskDescriptor { + private String description; + private String deadline; + + public UpdateTaskDescriptor() { + + } + + /** + * Constructor for updateTaskDescriptor object + * + */ + public UpdateTaskDescriptor(UpdateTaskDescriptor updateTaskDescriptor) { + setDeadline(updateTaskDescriptor.deadline); + setDescription(updateTaskDescriptor.description); + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return this.description; + } + + public void setDeadline(String deadline) { + this.deadline = deadline; + } + + public String getDeadline() { + return this.deadline; + } + + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof UpdateTaskDescriptor)) { + return false; + } + + // state check + UpdateTaskDescriptor e = (UpdateTaskDescriptor) other; + + return getDescription().equals(e.getDescription()) + && getDeadline().equals(e.getDeadline()); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 897071d3590..e77889a71a5 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -18,6 +18,7 @@ import seedu.address.logic.commands.FindTaskCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.UpdateTaskCommand; import seedu.address.logic.commands.ViewTaskCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -84,6 +85,9 @@ public Command parseCommand(String userInput) throws ParseException { case ViewTaskCommand.COMMAND_WORD: return new ViewTaskCommand(); + case UpdateTaskCommand.COMMAND_WORD: + return new UpdateTaskCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java new file mode 100644 index 00000000000..4f93a208557 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/UpdateTaskCommandParser.java @@ -0,0 +1,142 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; + +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.List; + +import seedu.address.logic.commands.AddTaskCommand; +import seedu.address.logic.commands.UpdateTaskCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +public class UpdateTaskCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the UpdateTaskCommand + * and returns an UpdateTask object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public UpdateTaskCommand parse(String args) throws ParseException { + requireNonNull(args); + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_ADD_TASK_DESCRIPTION, PREFIX_ADD_TASK_DEADLINE); + + Integer taskId; + + try { + taskId = ParserUtil.parseNumber(argMultimap.getPreamble()); + + // Throw exception if more than 1 description or deadline prefix exists + checkMultiplePrefixTokens(argMultimap); + + // Throw exception if no prefix exist + checkMinimumOnePrefix(argMultimap); + + // Throw exception if deadline does not adhere to specified format + checkDeadlineFormat(argMultimap); + + // Throw exception if empty prefix tokens are found + checkEmptyPrefix(argMultimap); + + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UpdateTaskCommand.MESSAGE_USAGE), pe); + } + + UpdateTaskCommand.UpdateTaskDescriptor updateTaskDescriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + + if (argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).isPresent()) { + updateTaskDescriptor.setDescription(argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).get()); + } + if (argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).isPresent()) { + updateTaskDescriptor.setDeadline(argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).get()); + } + + return new UpdateTaskCommand(taskId, updateTaskDescriptor); + } + + /** + * Check if more than 1 description or deadline prefix token exists in user input. + * Adapted from AddTaskCommandParser + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if more than 1 of the same prefix exists + */ + private void checkMultiplePrefixTokens(ArgumentMultimap argMultimap) throws ParseException { + List description = argMultimap.getAllValues(PREFIX_ADD_TASK_DESCRIPTION); + List deadline = argMultimap.getAllValues(PREFIX_ADD_TASK_DEADLINE); + + // Throw exception if more than 1 description or deadline token is used + if (description.size() > 1 || deadline.size() > 1) { + // more than 1 "d/" or "t/" prefix were used, meaning that it is wrong format + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UpdateTaskCommand.MESSAGE_USAGE)); + } + } + + /** + * Check if description prefix token exists in user input. + * Adapted from AddTaskCommandParser + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if prefix token does not exist + */ + private void checkMinimumOnePrefix(ArgumentMultimap argMultimap) throws ParseException { + List description = argMultimap.getAllValues(PREFIX_ADD_TASK_DESCRIPTION); + List deadline = argMultimap.getAllValues(PREFIX_ADD_TASK_DEADLINE); + + if (description.size() + deadline.size() < 1) { + // no prefix + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, + UpdateTaskCommand.MESSAGE_NOT_EDITED)); + } + } + + /** + * Check if prefix token values are empty. + * Adapted from AddTaskCommandParser + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if either token prefix value is empty + */ + private void checkEmptyPrefix(ArgumentMultimap argMultimap) throws ParseException { + if (argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).isPresent()) { + String description = argMultimap.getValue(PREFIX_ADD_TASK_DESCRIPTION).orElse(""); + if (description.equals("")) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } + if (argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).isPresent()) { + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + if (deadline.equals("")) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE)); + } + } + } + + /** + * Check if user's deadline input follows dd/MM/yyyy format. + * Adapted from AddTaskCommandParser + * + * @param argMultimap Tokenized user input + * @throws ParseException Throw exception if deadline does not follow the specified format + */ + private void checkDeadlineFormat(ArgumentMultimap argMultimap) throws ParseException { + String deadline = argMultimap.getValue(PREFIX_ADD_TASK_DEADLINE).orElse(""); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + + // If deadline is empty, return immediately without checking the format + if (deadline.equals("")) { + return; + } + + try { + dateTimeFormatter.parse(deadline); + } catch (DateTimeParseException e) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, UpdateTaskCommand.MESSAGE_USAGE)); + } + } + +} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 5da537d9164..551171bce63 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -99,4 +99,6 @@ public interface Model { String findTask(String input); String viewTask(); + + void updateTask(Task taskToUpdate, Task updatedTask); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index ffe4ef18c5e..7c2e7b615f6 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -183,4 +183,11 @@ public String findTask(String input) { public String viewTask() { return taskList.viewTask(); } + + //=========== Update Task =============== + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + taskToUpdate.updateDescription(updatedTask.getDescription()); + taskToUpdate.updateDeadline(updatedTask.getDeadline()); + } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 7b5309f1320..f1fb491e663 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -86,6 +86,15 @@ private String getOutput(ArrayList list) { } return sb.toString(); } + + /** + * Provides the task in the corresponding index + * @param taskId task id of the task to be retrieved + * @return task with the matching ID in task list + */ + public Task getTask(Integer taskId) { + return taskList.get(taskId - 1); // to convert to zero-based + } } diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 501f312da14..40029a18a7b 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -3,8 +3,9 @@ import static java.util.Objects.requireNonNull; public class Task { - private final String description; - private final String deadline; + + private String description; + private String deadline; /** * Initializes a Task with a description and deadline. @@ -16,6 +17,70 @@ public Task(String description, String deadline) { this.deadline = deadline; } + /** + * Updates description of task + * @param newDescription new description of task + */ + public void updateDescription(String newDescription) { + this.description = newDescription; + } + + /** + * Updates deadline of task + * @param newDeadline new deadline of task + */ + public void updateDeadline(String newDeadline) { + this.deadline = newDeadline; + } + + /** + * Getter to obtain description of task + * @return Description of task + */ + public String getDescription() { + return this.description; + } + + /** + * Getter to obtain deadline of task if any + * @return Deadline of task + */ + public String getDeadline() { + return this.deadline; + } + + /** + * Returns true if both task have the same description. + * Weaker notion of equality between two tasks + * @param otherTask Task object to be compared to + * @return boolean if the tasks compared have the same description + */ + public boolean isSameTask(Task otherTask) { + if (otherTask == this) { + return true; + } + return otherTask != null && otherTask.getDescription().equals(getDescription()); + } + + /** + * Returns true if both task have the same description and deadline. + * + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Task)) { + return false; + } + + Task otherTask = (Task) other; + return otherTask.getDescription().equals(getDescription()) + && otherTask.getDeadline().equals(getDeadline()); + } + @Override public String toString() { return "Task: " + this.description + " " + deadline; diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 8fd2b58ccfa..19ee73def49 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -174,6 +174,11 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 2b23974c754..94fe5d691cb 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -147,6 +147,11 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + throw new AssertionError("This method should not be called."); + } } private class ModelStubAcceptTask extends ModelStub { diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index d24c7663235..72dcd79326b 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -180,5 +180,10 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 242b40b58d3..5625a386d9a 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -179,6 +179,11 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index 599cbc3f6c2..1c31947bb21 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -140,6 +140,11 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public void updateTask(Task taskToUpdate, Task updatedTask) { + throw new AssertionError("This method should not be called."); + } } private class ModelStubViewTask extends ModelStub { From ecbfb1dd2fa50d6f35c6f6a3a2e956c4b60a6e30 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Sat, 26 Mar 2022 23:26:10 +0800 Subject: [PATCH 062/140] Update documentation of findt command --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index bb5f37372ec..5af51c775d9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -117,8 +117,8 @@ Locating tasks which match any of given keywords. Format:  `findt KEYWORD` - The search is case-insensitive. e.g. `lessons` will match `Lessons`. -- The order of the keywords does not matter. e.g. `drink water` will match `water drink` -- Choice of either full words matched or any tasks containing keyword. +- The order of the keywords matters. e.g. `drink water` will not match `water drink` +- Only full keyword(s) will be accepted. e.g. `drink` will match `drink`; `ink` will not match `drink` Example: `findt lessons` returns `Swimming lessons 03/05/2022`. From ee540ab989da68439c76b825f57f819f7c2f2a06 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Mon, 28 Mar 2022 00:10:42 +0800 Subject: [PATCH 063/140] Update implementation of update command to ensure task remains immutable. --- .../logic/commands/UpdateTaskCommand.java | 2 +- src/main/java/seedu/address/model/Model.java | 4 +++- .../seedu/address/model/ModelManager.java | 11 +++++++--- .../java/seedu/address/model/TaskList.java | 12 +++++++++++ .../java/seedu/address/model/task/Task.java | 20 ++----------------- .../logic/commands/AddCommandTest.java | 7 ++++++- .../logic/commands/AddTaskCommandTest.java | 7 ++++++- .../logic/commands/DeleteTaskCommandTest.java | 7 ++++++- .../logic/commands/FindTaskCommandTest.java | 7 ++++++- .../logic/commands/ViewTaskCommandTest.java | 7 ++++++- 10 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java index 4cc166fca04..b6f8c791f54 100644 --- a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -59,7 +59,7 @@ public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_DUPLICATE_TASK); } - model.updateTask(taskToUpdate, updatedTask); + model.updateTask(taskToUpdate, updatedTask, taskId); return new CommandResult(String.format(MESSAGE_UPDATE_TASK_SUCCESS, updatedTask)); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 551171bce63..f02ef5ee7a3 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -88,6 +88,8 @@ public interface Model { void addTask(Task task); + void addTask(Task task, Integer taskId); + TaskList getTaskList(); void deleteTask(Integer taskNumber); @@ -100,5 +102,5 @@ public interface Model { String viewTask(); - void updateTask(Task taskToUpdate, Task updatedTask); + void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 7c2e7b615f6..0ba10ff073a 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -159,6 +159,11 @@ public void addTask(Task task) { taskList.addTask(task); } + @Override + public void addTask(Task task, Integer taskId) { + taskList.addTask(task, taskId); + } + @Override public TaskList getTaskList() { return this.taskList; @@ -186,8 +191,8 @@ public String viewTask() { //=========== Update Task =============== @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { - taskToUpdate.updateDescription(updatedTask.getDescription()); - taskToUpdate.updateDeadline(updatedTask.getDeadline()); + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + taskList.deleteTask(taskId); + taskList.addTask(updatedTask, taskId); } } diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index f1fb491e663..8e94153f00c 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -23,6 +23,18 @@ public void addTask(Task task) { this.taskList.add(task); } + /** + * Add a task to the taskList at a specific index. + * + * @param task the Task to be added which must not be null + * @param taskId the location to be added in which must not be null + */ + public void addTask(Task task, Integer taskId) { + requireNonNull(task); + requireNonNull(taskId); + this.taskList.add(taskId - 1, task); // to convert to zero-based indexing + } + /** * Returns the taskList. * diff --git a/src/main/java/seedu/address/model/task/Task.java b/src/main/java/seedu/address/model/task/Task.java index 40029a18a7b..8de70ca55b8 100644 --- a/src/main/java/seedu/address/model/task/Task.java +++ b/src/main/java/seedu/address/model/task/Task.java @@ -4,8 +4,8 @@ public class Task { - private String description; - private String deadline; + private final String description; + private final String deadline; /** * Initializes a Task with a description and deadline. @@ -17,22 +17,6 @@ public Task(String description, String deadline) { this.deadline = deadline; } - /** - * Updates description of task - * @param newDescription new description of task - */ - public void updateDescription(String newDescription) { - this.description = newDescription; - } - - /** - * Updates deadline of task - * @param newDeadline new deadline of task - */ - public void updateDeadline(String newDeadline) { - this.deadline = newDeadline; - } - /** * Getter to obtain description of task * @return Description of task diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 19ee73def49..48d07e98cf3 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -155,6 +155,11 @@ public void addTask(Task task) { throw new AssertionError("This method should not be called."); } + @Override + public void addTask(Task task, Integer taskId) { + throw new AssertionError("This method should not be called."); + } + @Override public TaskList getTaskList() { throw new AssertionError("This method should not be called."); @@ -176,7 +181,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 94fe5d691cb..7daf5d52444 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -128,6 +128,11 @@ public void addTask(Task task) { throw new AssertionError("This method should not be called."); } + @Override + public void addTask(Task task, Integer taskId) { + throw new AssertionError("This method should not be called."); + } + @Override public TaskList getTaskList() { throw new AssertionError("This method should not be called."); @@ -149,7 +154,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index 72dcd79326b..adf3016017e 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -161,6 +161,11 @@ public void addTask(Task task) { throw new AssertionError("This method should not be called."); } + @Override + public void addTask(Task task, Integer taskId) { + throw new AssertionError("This method should not be called."); + } + @Override public void deleteTask(Integer taskNumber) { throw new AssertionError("This method should not be called."); @@ -182,7 +187,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 5625a386d9a..2b0b4222f86 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -160,6 +160,11 @@ public void addTask(Task task) { throw new AssertionError("This method should not be called."); } + @Override + public void addTask(Task task, Integer taskId) { + throw new AssertionError("This method should not be called."); + } + @Override public void deleteTask(Integer taskNumber) { throw new AssertionError("This method should not be called."); @@ -181,7 +186,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index 1c31947bb21..1e8ef6fe6cf 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -121,6 +121,11 @@ public void addTask(Task task) { throw new AssertionError("This method should not be called."); } + @Override + public void addTask(Task task, Integer taskId) { + throw new AssertionError("This method should not be called."); + } + @Override public TaskList getTaskList() { throw new AssertionError("This method should not be called."); @@ -142,7 +147,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask) { + public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } From aed47b189a9587c852d75320d5f289765209c590 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:25:28 +0800 Subject: [PATCH 064/140] Cover test for TaskList Storage implementation - Add JsonAdaptedTaskTest - Add JsonSerializableTaskListTest - Add JsonTaskListStorageTest - Add TypicalTask - Modify current tests to use the new StrageManager constructor --- .../invalidTaskTaskList.json | 6 + .../typicalTaskTaskList.json | 6 + .../invalidAndValidTaskTaskList.json | 9 ++ .../invalidTaskTaskList.json | 6 + .../notJsonFormatAddressBook.json | 1 + .../seedu/address/logic/LogicManagerTest.java | 9 +- .../commands/AddCommandIntegrationTest.java | 5 +- .../logic/commands/AddCommandTest.java | 16 +++ .../logic/commands/AddTaskCommandTest.java | 16 +++ .../logic/commands/ClearCommandTest.java | 5 +- .../logic/commands/DeleteCommandTest.java | 7 +- .../logic/commands/DeleteTaskCommandTest.java | 19 +++- .../logic/commands/EditCommandTest.java | 15 ++- .../logic/commands/FindCommandTest.java | 5 +- .../logic/commands/FindTaskCommandTest.java | 19 +++- .../logic/commands/ListCommandTest.java | 5 +- .../logic/commands/ViewTaskCommandTest.java | 16 +++ .../seedu/address/model/ModelManagerTest.java | 11 +- .../seedu/address/model/TaskListTest.java | 20 ++++ .../seedu/address/model/UserPrefsTest.java | 5 + .../seedu/address/model/task/TaskTest.java | 12 ++ .../address/storage/JsonAdaptedTaskTest.java | 33 ++++++ .../storage/JsonSerializableTaskListTest.java | 36 ++++++ .../storage/JsonTaskListStorageTest.java | 103 ++++++++++++++++++ .../address/storage/StorageManagerTest.java | 18 ++- .../seedu/address/testutil/TypicalTask.java | 26 +++++ 26 files changed, 402 insertions(+), 27 deletions(-) create mode 100644 src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json create mode 100644 src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json create mode 100644 src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json create mode 100644 src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json create mode 100644 src/test/data/JsonTaskListStorageTest/notJsonFormatAddressBook.json create mode 100644 src/test/java/seedu/address/storage/JsonAdaptedTaskTest.java create mode 100644 src/test/java/seedu/address/storage/JsonSerializableTaskListTest.java create mode 100644 src/test/java/seedu/address/storage/JsonTaskListStorageTest.java create mode 100644 src/test/java/seedu/address/testutil/TypicalTask.java diff --git a/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json b/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json new file mode 100644 index 00000000000..3a4ac63c303 --- /dev/null +++ b/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json @@ -0,0 +1,6 @@ +{ + "tasks" : [ { + "description" : null, + "deadline" : "01/01/2022" + } ] +} \ No newline at end of file diff --git a/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json b/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json new file mode 100644 index 00000000000..9a777c79157 --- /dev/null +++ b/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json @@ -0,0 +1,6 @@ +{ + "tasks" : [ { + "description" : "dummy", + "deadline" : "01/01/2022" + } ] +} \ No newline at end of file diff --git a/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json b/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json new file mode 100644 index 00000000000..ede31f7f285 --- /dev/null +++ b/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json @@ -0,0 +1,9 @@ +{ + "tasks" : [ { + "description" : null, + "deadline" : "01/01/2022" + }, { + "description" : "dummy", + "deadline" : "01/01/2022" + } ] +} \ No newline at end of file diff --git a/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json b/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json new file mode 100644 index 00000000000..3a4ac63c303 --- /dev/null +++ b/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json @@ -0,0 +1,6 @@ +{ + "tasks" : [ { + "description" : null, + "deadline" : "01/01/2022" + } ] +} \ No newline at end of file diff --git a/src/test/data/JsonTaskListStorageTest/notJsonFormatAddressBook.json b/src/test/data/JsonTaskListStorageTest/notJsonFormatAddressBook.json new file mode 100644 index 00000000000..a1097343b5d --- /dev/null +++ b/src/test/data/JsonTaskListStorageTest/notJsonFormatAddressBook.json @@ -0,0 +1 @@ +not json format! diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index ad923ac249a..13d18e77905 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -28,6 +28,7 @@ import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.storage.JsonAddressBookStorage; +import seedu.address.storage.JsonTaskListStorage; import seedu.address.storage.JsonUserPrefsStorage; import seedu.address.storage.StorageManager; import seedu.address.testutil.PersonBuilder; @@ -46,7 +47,8 @@ public void setUp() { JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json")); - StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage); + JsonTaskListStorage taskListStorage = new JsonTaskListStorage(temporaryFolder.resolve("tasklist.json")); + StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage, taskListStorage); logic = new LogicManager(model, storage); } @@ -75,7 +77,8 @@ public void execute_storageThrowsIoException_throwsCommandException() { new JsonAddressBookIoExceptionThrowingStub(temporaryFolder.resolve("ioExceptionAddressBook.json")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("ioExceptionUserPrefs.json")); - StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage); + JsonTaskListStorage taskListStorage = new JsonTaskListStorage(temporaryFolder.resolve("tasklist.json")); + StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage, taskListStorage); logic = new LogicManager(model, storage); // Execute add command @@ -129,7 +132,7 @@ private void assertCommandException(String inputCommand, String expectedMessage) */ private void assertCommandFailure(String inputCommand, Class expectedException, String expectedMessage) { - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs(), model.getTaskList()); assertCommandFailure(inputCommand, expectedException, expectedMessage, expectedModel); } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java index cb8714bb055..88112cbe94d 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java @@ -3,6 +3,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -22,14 +23,14 @@ public class AddCommandIntegrationTest { @BeforeEach public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); } @Test public void execute_newPerson_success() { Person validPerson = new PersonBuilder().build(); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs(), model.getTaskList()); expectedModel.addPerson(validPerson); assertCommandSuccess(new AddCommand(validPerson), model, diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 8fd2b58ccfa..c4e188749fa 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -19,6 +19,7 @@ import seedu.address.model.AddressBook; import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; import seedu.address.model.person.Person; @@ -174,6 +175,21 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public Path getTaskListFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 2b23974c754..e8e8fdfbf0b 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -13,6 +13,7 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; import seedu.address.model.person.Person; @@ -147,6 +148,21 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public Path getTaskListFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } } private class ModelStubAcceptTask extends ModelStub { diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java index 80d9110c03a..ab4935dd9b6 100644 --- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java @@ -2,6 +2,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import org.junit.jupiter.api.Test; @@ -22,8 +23,8 @@ public void execute_emptyAddressBook_success() { @Test public void execute_nonEmptyAddressBook_success() { - Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); + Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); expectedModel.setAddressBook(new AddressBook()); assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel); diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index 45a8c910ba1..cbc79b3d9bb 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -8,6 +8,7 @@ import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import org.junit.jupiter.api.Test; @@ -24,7 +25,7 @@ */ public class DeleteCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test public void execute_validIndexUnfilteredList_success() { @@ -33,7 +34,7 @@ public void execute_validIndexUnfilteredList_success() { String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs(), model.getTaskList()); expectedModel.deletePerson(personToDelete); assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); @@ -56,7 +57,7 @@ public void execute_validIndexFilteredList_success() { String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, personToDelete); - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs(), model.getTaskList()); expectedModel.deletePerson(personToDelete); showNoPerson(expectedModel); diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index d24c7663235..1d4511f3399 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -6,6 +6,7 @@ import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import java.nio.file.Path; import java.util.function.Predicate; @@ -18,6 +19,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; import seedu.address.model.UserPrefs; @@ -26,7 +28,7 @@ public class DeleteTaskCommandTest { - private ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test public void constructor_validInputSuccess() throws Exception { @@ -180,5 +182,20 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public Path getTaskListFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 214c6c2507b..d03e30c5e5c 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -13,6 +13,7 @@ import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import org.junit.jupiter.api.Test; @@ -32,7 +33,7 @@ */ public class EditCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test public void execute_allFieldsSpecifiedUnfilteredList_success() { @@ -42,7 +43,8 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs(), + model.getTaskList()); expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); @@ -63,7 +65,8 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs(), + model.getTaskList()); expectedModel.setPerson(lastPerson, editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); @@ -76,7 +79,8 @@ public void execute_noFieldSpecifiedUnfilteredList_success() { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs(), + model.getTaskList()); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); } @@ -92,7 +96,8 @@ public void execute_filteredList_success() { String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, editedPerson); - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs(), + model.getTaskList()); expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson); assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index 9b15db28bbb..8d43b80dc40 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -9,6 +9,7 @@ import static seedu.address.testutil.TypicalPersons.ELLE; import static seedu.address.testutil.TypicalPersons.FIONA; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import java.util.Arrays; import java.util.Collections; @@ -24,8 +25,8 @@ * Contains integration tests (interaction with the Model) for {@code FindCommand}. */ public class FindCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); + private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test public void equals() { diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 242b40b58d3..db9cd9b3769 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.testutil.Assert.assertThrows; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import java.nio.file.Path; import java.util.function.Predicate; @@ -17,6 +18,7 @@ import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; import seedu.address.model.UserPrefs; @@ -28,7 +30,7 @@ */ public class FindTaskCommandTest { - private final ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private final ModelManager model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test public void constructor_nullInput_throwsNullPointerException() { @@ -179,6 +181,21 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public Path getTaskListFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } } } diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index 435ff1f7275..d7aa19a9f51 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -4,6 +4,7 @@ import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -22,8 +23,8 @@ public class ListCommandTest { @BeforeEach public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); + expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs(), model.getTaskList()); } @Test diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index 599cbc3f6c2..63a4896f506 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -14,6 +14,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.TaskList; import seedu.address.model.person.Person; @@ -140,6 +141,21 @@ public String findTask(String input) { public String viewTask() { throw new AssertionError("This method should not be called."); } + + @Override + public Path getTaskListFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setTaskListFilePath(Path taskListFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } } private class ModelStubViewTask extends ModelStub { diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 2cf1418d116..032bcbd40b0 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -98,10 +98,11 @@ public void equals() { AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build(); AddressBook differentAddressBook = new AddressBook(); UserPrefs userPrefs = new UserPrefs(); + TaskList taskList = new TaskList(); // same values -> returns true - modelManager = new ModelManager(addressBook, userPrefs); - ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs); + modelManager = new ModelManager(addressBook, userPrefs, taskList); + ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs, taskList); assertTrue(modelManager.equals(modelManagerCopy)); // same object -> returns true @@ -114,12 +115,12 @@ public void equals() { assertFalse(modelManager.equals(5)); // different addressBook -> returns false - assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs))); + assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs, taskList))); // different filteredList -> returns false String[] keywords = ALICE.getName().fullName.split("\\s+"); modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); - assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs))); + assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs, taskList))); // resets modelManager to initial state for upcoming tests modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); @@ -127,6 +128,6 @@ public void equals() { // different userPrefs -> returns false UserPrefs differentUserPrefs = new UserPrefs(); differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath")); - assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs))); + assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs, taskList))); } } diff --git a/src/test/java/seedu/address/model/TaskListTest.java b/src/test/java/seedu/address/model/TaskListTest.java index 248a18ea49b..b7a0fd392fe 100644 --- a/src/test/java/seedu/address/model/TaskListTest.java +++ b/src/test/java/seedu/address/model/TaskListTest.java @@ -2,12 +2,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import java.util.ArrayList; import java.util.Collections; import org.junit.jupiter.api.Test; +import javafx.collections.ObservableList; import seedu.address.model.task.Task; public class TaskListTest { @@ -30,4 +32,22 @@ public void addTask_success() { public void addTask_null_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> taskList.addTask(null)); } + + @Test + public void resetData_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> taskList.resetData(null)); + } + + @Test + public void resetData_withValidReadOnlyTaskList_replacesData() { + TaskList newData = getTypicalTaskList(); + taskList.resetData(newData); + assertEquals(newData.getTaskList(), taskList.getTaskList()); + } + + @Test + public void getObservableTaskList_success() { + ObservableList observableTaskList = taskList.getObservableTaskList(); + assertEquals(observableTaskList, taskList.getTaskList()); + } } diff --git a/src/test/java/seedu/address/model/UserPrefsTest.java b/src/test/java/seedu/address/model/UserPrefsTest.java index b1307a70d52..0bd443c111e 100644 --- a/src/test/java/seedu/address/model/UserPrefsTest.java +++ b/src/test/java/seedu/address/model/UserPrefsTest.java @@ -18,4 +18,9 @@ public void setAddressBookFilePath_nullPath_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null)); } + @Test + public void setTaskListFilePath_nullPath_throwsNullPointerException() { + UserPrefs userPrefs = new UserPrefs(); + assertThrows(NullPointerException.class, () -> userPrefs.setTaskListFilePath(null)); + } } diff --git a/src/test/java/seedu/address/model/task/TaskTest.java b/src/test/java/seedu/address/model/task/TaskTest.java index 26f91c77440..3f924fa3a89 100644 --- a/src/test/java/seedu/address/model/task/TaskTest.java +++ b/src/test/java/seedu/address/model/task/TaskTest.java @@ -22,6 +22,18 @@ public void constructor_deadlineNull_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> new Task("description", null)); } + @Test + public void getDescription_success() { + Task task = new Task("dummy", "01/01/2022"); + assertEquals("dummy", task.getDescription()); + } + + @Test + public void getDeadline_success() { + Task task = new Task("dummy", "01/01/2022"); + assertEquals("01/01/2022", task.getDeadline()); + } + @Test public void toString_success() { Task task = new Task("description", "2022"); diff --git a/src/test/java/seedu/address/storage/JsonAdaptedTaskTest.java b/src/test/java/seedu/address/storage/JsonAdaptedTaskTest.java new file mode 100644 index 00000000000..008dd2fd8e4 --- /dev/null +++ b/src/test/java/seedu/address/storage/JsonAdaptedTaskTest.java @@ -0,0 +1,33 @@ +package seedu.address.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.storage.JsonAdaptedTask.MISSING_FIELD_MESSAGE_FORMAT; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalTask.DUMMY_TASK; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.exceptions.IllegalValueException; + +class JsonAdaptedTaskTest { + + @Test + public void toModelType_validTask_returnsTask() throws Exception { + JsonAdaptedTask task = new JsonAdaptedTask("dummy", "01/01/2022"); + assertEquals(DUMMY_TASK.toString(), task.toModelType().toString()); + } + + @Test + void toModelType_nullDescription_throwsIllegalValueException() { + JsonAdaptedTask task = new JsonAdaptedTask(null, "01/01/2022"); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, "description"); + assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } + + @Test + void toModelType_nullDeadline_throwsIllegalValueException() { + JsonAdaptedTask task = new JsonAdaptedTask("description", null); + String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, "deadline"); + assertThrows(IllegalValueException.class, expectedMessage, task::toModelType); + } +} diff --git a/src/test/java/seedu/address/storage/JsonSerializableTaskListTest.java b/src/test/java/seedu/address/storage/JsonSerializableTaskListTest.java new file mode 100644 index 00000000000..5f484f32da5 --- /dev/null +++ b/src/test/java/seedu/address/storage/JsonSerializableTaskListTest.java @@ -0,0 +1,36 @@ +package seedu.address.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static seedu.address.testutil.Assert.assertThrows; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.exceptions.IllegalValueException; +import seedu.address.commons.util.JsonUtil; +import seedu.address.model.TaskList; +import seedu.address.testutil.TypicalTask; + +class JsonSerializableTaskListTest { + private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableTaskListTest"); + private static final Path TYPICAL_TASK_FILE = TEST_DATA_FOLDER.resolve("typicalTaskTaskList.json"); + private static final Path INVALID_TASK_FILE = TEST_DATA_FOLDER.resolve("invalidTaskTaskList.json"); + + @Test + public void toModelType_typicalTaskFile_success() throws Exception { + JsonSerializableTaskList dataFromFile = JsonUtil.readJsonFile(TYPICAL_TASK_FILE, + JsonSerializableTaskList.class).get(); + TaskList taskListFromFile = dataFromFile.toModelType(); + TaskList typicalTaskList = TypicalTask.getTypicalTaskList(); + assertEquals(taskListFromFile.getTaskList().toString(), typicalTaskList.getTaskList().toString()); + } + + @Test + public void toModelType_invalidTaskFile_throwsIllegalValueException() throws Exception { + JsonSerializableTaskList dataFromFile = JsonUtil.readJsonFile(INVALID_TASK_FILE, + JsonSerializableTaskList.class).get(); + assertThrows(IllegalValueException.class, dataFromFile::toModelType); + } +} diff --git a/src/test/java/seedu/address/storage/JsonTaskListStorageTest.java b/src/test/java/seedu/address/storage/JsonTaskListStorageTest.java new file mode 100644 index 00000000000..ee04d26bf8d --- /dev/null +++ b/src/test/java/seedu/address/storage/JsonTaskListStorageTest.java @@ -0,0 +1,103 @@ +package seedu.address.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.TaskList; +import seedu.address.model.task.Task; + +class JsonTaskListStorageTest { + private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonTaskListStorageTest"); + + @TempDir + public Path testFolder; + + @Test + public void readTaskList_nullFilePath_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> readTaskList(null)); + } + + private java.util.Optional readTaskList(String filePath) throws Exception { + return new JsonTaskListStorage(Paths.get(filePath)).readTaskList(addToTestDataPathIfNotNull(filePath)); + } + + private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) { + return prefsFileInTestDataFolder != null + ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder) + : null; + } + + @Test + public void readTaskList_missingFile_emptyResult() throws Exception { + assertFalse(readTaskList("NonExistentFile.json").isPresent()); + } + + @Test + public void readTaskList_notJsonFormat_exceptionThrown() { + assertThrows(DataConversionException.class, () -> readTaskList("notJsonFormatAddressBook.json")); + } + + @Test + public void readTaskList_invalidPersonAddressBook_throwDataConversionException() { + assertThrows(DataConversionException.class, () -> readTaskList("invalidTaskTaskList.json")); + } + + @Test + public void readTaskList_invalidAndValidPersonAddressBook_throwDataConversionException() { + assertThrows(DataConversionException.class, () -> readTaskList("invalidAndValidTaskTaskList.json")); + } + + @Test + public void readAndSaveAddressBook_allInOrder_success() throws Exception { + Path filePath = testFolder.resolve("TempAddressBook.json"); + TaskList original = getTypicalTaskList(); + JsonTaskListStorage jsonTaskListStorage = new JsonTaskListStorage(filePath); + + // Save in new file and read back + jsonTaskListStorage.saveTaskList(original, filePath); + ReadOnlyTaskList readBack = jsonTaskListStorage.readTaskList(filePath).get(); + assertEquals(original.getTaskList().toString(), new TaskList(readBack).getTaskList().toString()); + + // Modify data, overwrite exiting file, and read back + original.addTask(new Task("dummy", "01/01/2022")); + original.deleteTask(1); + jsonTaskListStorage.saveTaskList(original, filePath); + readBack = jsonTaskListStorage.readTaskList(filePath).get(); + assertEquals(original.getTaskList().toString(), new TaskList(readBack).getTaskList().toString()); + + // Save and read without specifying file path + original.addTask(new Task("dummy", "01/01/2022")); + jsonTaskListStorage.saveTaskList(original); // file path not specified + readBack = jsonTaskListStorage.readTaskList().get(); // file path not specified + assertEquals(original.getTaskList().toString(), new TaskList(readBack).getTaskList().toString()); + } + + @Test + public void saveTaskList_nullTaskList_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> saveTaskList(null, "SomeFile.json")); + } + + private void saveTaskList(ReadOnlyTaskList taskList, String filePath) { + try { + new JsonTaskListStorage(Paths.get(filePath)).saveTaskList(taskList, addToTestDataPathIfNotNull(filePath)); + } catch (IOException ioe) { + throw new AssertionError("There should not be an error writing to the file.", ioe); + } + } + + @Test + public void saveTaskList_nullFilePath_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> saveTaskList(new TaskList(), null)); + } +} diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java index 99a16548970..ca7ffff8383 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/seedu/address/storage/StorageManagerTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; import java.nio.file.Path; @@ -13,6 +14,8 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.model.AddressBook; import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.TaskList; import seedu.address.model.UserPrefs; public class StorageManagerTest { @@ -26,7 +29,8 @@ public class StorageManagerTest { public void setUp() { JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(getTempFilePath("ab")); JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs")); - storageManager = new StorageManager(addressBookStorage, userPrefsStorage); + JsonTaskListStorage taskListStorage = new JsonTaskListStorage(getTempFilePath("tasklist")); + storageManager = new StorageManager(addressBookStorage, userPrefsStorage, taskListStorage); } private Path getTempFilePath(String fileName) { @@ -65,4 +69,16 @@ public void getAddressBookFilePath() { assertNotNull(storageManager.getAddressBookFilePath()); } + @Test + public void taskListReadSave() throws Exception { + TaskList original = getTypicalTaskList(); + storageManager.saveTaskList(original); + ReadOnlyTaskList retrieved = storageManager.readTaskList().get(); + assertEquals(original.getTaskList().toString(), new TaskList(retrieved).getTaskList().toString()); + } + + @Test + public void getTaskListFilePath() { + assertNotNull(storageManager.getTaskListFilePath()); + } } diff --git a/src/test/java/seedu/address/testutil/TypicalTask.java b/src/test/java/seedu/address/testutil/TypicalTask.java new file mode 100644 index 00000000000..97cc05dffe7 --- /dev/null +++ b/src/test/java/seedu/address/testutil/TypicalTask.java @@ -0,0 +1,26 @@ +package seedu.address.testutil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import seedu.address.model.TaskList; +import seedu.address.model.task.Task; + +public class TypicalTask { + public static final Task DUMMY_TASK = new Task("dummy", "01/01/2022"); + + private TypicalTask() {} // prevent instantiation + + public static TaskList getTypicalTaskList() { + TaskList taskList = new TaskList(); + for (Task task : getTypicalTask()) { + taskList.addTask(task); + } + return taskList; + } + + public static List getTypicalTask() { + return new ArrayList<>(Arrays.asList(DUMMY_TASK)); + } +} From bad4dcbbefd588739ef6cb4fae85605bc1273fc1 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:35:27 +0800 Subject: [PATCH 065/140] Update code to follow checkstyleMain --- src/main/java/seedu/address/MainApp.java | 18 ++++++++++++++++-- .../java/seedu/address/model/TaskList.java | 13 +++++++++++++ .../address/model/util/SampleDataUtil.java | 2 +- .../seedu/address/storage/JsonAdaptedTask.java | 18 +++++++++++------- .../storage/JsonSerializableTaskList.java | 7 ++++++- .../address/storage/JsonTaskListStorage.java | 11 +++++++++++ .../seedu/address/storage/StorageManager.java | 5 +++-- 7 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 9840bb52296..a305070348b 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -15,9 +15,23 @@ import seedu.address.commons.util.StringUtil; import seedu.address.logic.Logic; import seedu.address.logic.LogicManager; -import seedu.address.model.*; +import seedu.address.model.AddressBook; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.ReadOnlyAddressBook; +import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.ReadOnlyUserPrefs; +import seedu.address.model.TaskList; +import seedu.address.model.UserPrefs; import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.*; +import seedu.address.storage.AddressBookStorage; +import seedu.address.storage.JsonAddressBookStorage; +import seedu.address.storage.JsonTaskListStorage; +import seedu.address.storage.JsonUserPrefsStorage; +import seedu.address.storage.Storage; +import seedu.address.storage.StorageManager; +import seedu.address.storage.TaskListStorage; +import seedu.address.storage.UserPrefsStorage; import seedu.address.ui.Ui; import seedu.address.ui.UiManager; diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index ed4b7c7bbd9..200672cb3a5 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -12,17 +12,30 @@ public class TaskList implements ReadOnlyTaskList { private final ArrayList taskList; + /* + * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication + * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html + * + * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication + * among constructors. + */ { taskList = new ArrayList<>(); } public TaskList() {} + /** + * Creates a TaskList using the Tasks in the {@code toBeCopied} + */ public TaskList(ReadOnlyTaskList toBeCopied) { this(); resetData(toBeCopied); } + /** + * Resets the existing data of this {@code TaskList} with {@code newData}. + */ public void resetData(ReadOnlyTaskList newData) { requireNonNull(newData); diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 543ff498d40..bb5c724f0fe 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -62,7 +62,7 @@ public static Set getTagSet(String... strings) { public static Task[] getSampleTask() { return new Task[] { - new Task("dummy", "01/01/2022") + new Task("dummy", "01/01/2022") }; } diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTask.java b/src/main/java/seedu/address/storage/JsonAdaptedTask.java index caa9f9d410c..fe0bbe9d5f6 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedTask.java +++ b/src/main/java/seedu/address/storage/JsonAdaptedTask.java @@ -1,11 +1,5 @@ package seedu.address.storage; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -19,17 +13,27 @@ public class JsonAdaptedTask { private final String description; private final String deadline; + /** + * Constructs a {@code JsonAdaptedTask} with the given task details. + */ @JsonCreator public JsonAdaptedTask(@JsonProperty("description") String description, @JsonProperty("deadline") String deadline) { this.description = description; this.deadline = deadline; } - + /** + * Converts a given {@code Task} into this class for Jackson use. + */ public JsonAdaptedTask(Task source) { description = source.getDescription(); deadline = source.getDeadline(); } + /** + * Converts this Jackson-friendly adapted person object into the model's {@code Task} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted task. + */ public Task toModelType() throws IllegalValueException { if (description == null) { throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, "description")); diff --git a/src/main/java/seedu/address/storage/JsonSerializableTaskList.java b/src/main/java/seedu/address/storage/JsonSerializableTaskList.java index 8f225f98a06..1600d513abd 100644 --- a/src/main/java/seedu/address/storage/JsonSerializableTaskList.java +++ b/src/main/java/seedu/address/storage/JsonSerializableTaskList.java @@ -9,8 +9,8 @@ import com.fasterxml.jackson.annotation.JsonRootName; import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.TaskList; import seedu.address.model.ReadOnlyTaskList; +import seedu.address.model.TaskList; import seedu.address.model.task.Task; /** @@ -30,6 +30,11 @@ public JsonSerializableTaskList(ReadOnlyTaskList source) { tasks.addAll(source.getObservableTaskList().stream().map(JsonAdaptedTask::new).collect(Collectors.toList())); } + /** + * Converts this task list into the model's {@code TaskList} object. + * + * @throws IllegalValueException if there were any data constraints violated. + */ public TaskList toModelType() throws IllegalValueException { TaskList taskList = new TaskList(); for (JsonAdaptedTask jsonAdaptedTask : tasks) { diff --git a/src/main/java/seedu/address/storage/JsonTaskListStorage.java b/src/main/java/seedu/address/storage/JsonTaskListStorage.java index d57d4272ce4..002b4c97876 100644 --- a/src/main/java/seedu/address/storage/JsonTaskListStorage.java +++ b/src/main/java/seedu/address/storage/JsonTaskListStorage.java @@ -33,6 +33,12 @@ public Optional readTaskList() throws DataConversionException, return readTaskList(filePath); } + /** + * Similar to {@link #readTaskList()}. + * + * @param filePath location of the data. Cannot be null. + * @throws DataConversionException if the file is not in the correct format. + */ public Optional readTaskList(Path filePath) throws DataConversionException, IOException { requireNonNull(filePath); @@ -55,6 +61,11 @@ public void saveTaskList(ReadOnlyTaskList taskList) throws IOException { saveTaskList(taskList, filePath); } + /** + * Similar to {@link #saveTaskList(ReadOnlyTaskList)}. + * + * @param filePath location of the data. Cannot be null. + */ public void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException { requireNonNull(taskList); requireNonNull(filePath); diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java index 55947b87934..28a5f93fcf1 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/seedu/address/storage/StorageManager.java @@ -25,7 +25,8 @@ public class StorageManager implements Storage { /** * Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}. */ - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage, TaskListStorage taskListStorage) { + public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage, + TaskListStorage taskListStorage) { this.addressBookStorage = addressBookStorage; this.userPrefsStorage = userPrefsStorage; this.taskListStorage = taskListStorage; @@ -101,7 +102,7 @@ public void saveTaskList(ReadOnlyTaskList taskList) throws IOException { } @Override - public void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException{ + public void saveTaskList(ReadOnlyTaskList taskList, Path filePath) throws IOException { logger.fine("Attempting to write to data file: " + filePath); taskListStorage.saveTaskList(taskList, filePath); } From 4c662832000ce34dcb7b80a5244d6ca6bc56db5f Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:41:36 +0800 Subject: [PATCH 066/140] Remove trailing whitespaces in documents --- README.md | 2 +- docs/AboutUs.md | 4 +--- docs/DeveloperGuide.md | 2 +- docs/UserGuide.md | 12 ++++++------ docs/index.md | 2 +- docs/team/yumengtan.md | 10 +++++----- .../invalidTaskTaskList.json | 2 +- .../typicalTaskTaskList.json | 2 +- .../invalidAndValidTaskTaskList.json | 2 +- .../JsonTaskListStorageTest/invalidTaskTaskList.json | 2 +- 10 files changed, 19 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 8395b988643..3f737e2b824 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona * View all tasks and their deadlines * View all contacts * Remind upcoming tasks - * + ## Acknowledgements *** This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative.](https://se-education.org) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 7653de14518..69717777711 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -26,16 +26,14 @@ You can reach us at the email `e0544443@u.nus.edu` [[portfolio](team/castryl.md)] * Role: Documentation -* ### Ivor Chua -[[github](http://github.com/ivorcmx)] +[[github](http://github.com/ivorcmx)] [[portfolio](team/ivorcmx.md)] * Role: Testing -* ### Tan Yu Meng diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ddbf7c86352..be595844a56 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -271,7 +271,7 @@ The following sequence diagram shows how the add task operation work assuming no The proposed find task feature is facilitated by `FindTaskCommand`. It extends `Command` and makes use of the `TaskList` model and `Task`. The `TaskList` Model is used to retrieve the `Tasks` that have been stored. The `FindTaskCommand` also has a `FindTaskCommandParser` to do the logical parsing of the user's input. It uses regex to ignore case sensitivity of user's input. -These are the operations that the feature implements: +These are the operations that the feature implements: * `FindTaskCommand#execute()` : Executes the command. * `FindTaskCommandParser#parse()` : Parses the user input and returns a `FindTaskCommand` Object. * `TaskList#findTask()` : Finds and returns tasks matching keyword from user input (ignores case sensitivity) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index bb5f37372ec..f6cfd5edfd0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -3,8 +3,8 @@ layout: page title: User Guide --- #User Guide - NUScheduler -NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, -optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. - Quick Start @@ -61,12 +61,12 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona **Notes about the command format:** -- Words in **UPPER_CASE** are the parameters to be supplied by the user.e.g. in `add t n /NAME`, **NAME** is a parameter +- Words in **UPPER_CASE** are the parameters to be supplied by the user.e.g. in `add t n /NAME`, **NAME** is a parameter. - which can be used as `add t n /John Doe`. - Items in **square brackets** are optional.e.g `/NAME [/TAG]` can be used as `/John Doe /friend` or as `/John Doe`. -- Parameters cannot be in any order and must follow the order given in the command format.e.g. if the command format +- Parameters cannot be in any order and must follow the order given in the command format.e.g. if the command format. - specifies `add t /DESCRIPTION /DEADLINE [/TAG]`, the details must be entered as `/DESCRIPTION /DEADLINE [/TAG]`. -- All `` fields must be > 0 +- All `` fields must be > 0. @@ -203,7 +203,7 @@ NUScheduler data is saved in the hard disk automatically after any command that **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 +**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 NUScheduler home folder. -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/index.md b/docs/index.md index d5addeb9095..a446738f1b4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,7 +8,7 @@ title: NUScheduler ![Ui](images/Ui.png) -**NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts**, +**NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts**, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. diff --git a/docs/team/yumengtan.md b/docs/team/yumengtan.md index 5e3fd037808..095e2527bcb 100644 --- a/docs/team/yumengtan.md +++ b/docs/team/yumengtan.md @@ -3,8 +3,8 @@ layout: page title: Tan Yu Meng's Project Portfolio Page --- ### Project: NUScheduler -NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, -optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). +NUScheduler is a desktop app for Year 1 Computing students to assist with more efficient management of tasks and contacts, +optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, NUScheduler can schedule your tasks faster than traditional GUI apps. Given below are my contributions to the project. @@ -18,9 +18,9 @@ Given below are my contributions to the project. * **Tests Written**: * `FindTaskCommandTest` * **Additional info**: - * Used regex to ignore case sensitivity from user input. + * Used regex to ignore case sensitivity from user input. -* **New Feature**: +* **New Feature**: * to be added soon * **Code contributed**: [RepoSense link (to be added soon)]() @@ -38,7 +38,7 @@ Given below are my contributions to the project. * Added documentation for the feature `FindTask`. * Developer Guide: * Contribute to glossary in the developer guide. - * Added user story for find task feature. + * Added user story for find task feature. * Added MSS for `FindTask`. * Diagrams * Added Sequence Diagram for `FindTask` diff --git a/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json b/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json index 3a4ac63c303..8115d138a2c 100644 --- a/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json +++ b/src/test/data/JsonSerializableTaskListTest/invalidTaskTaskList.json @@ -3,4 +3,4 @@ "description" : null, "deadline" : "01/01/2022" } ] -} \ No newline at end of file +} diff --git a/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json b/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json index 9a777c79157..ca6f89f553f 100644 --- a/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json +++ b/src/test/data/JsonSerializableTaskListTest/typicalTaskTaskList.json @@ -3,4 +3,4 @@ "description" : "dummy", "deadline" : "01/01/2022" } ] -} \ No newline at end of file +} diff --git a/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json b/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json index ede31f7f285..c2075b0986f 100644 --- a/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json +++ b/src/test/data/JsonTaskListStorageTest/invalidAndValidTaskTaskList.json @@ -6,4 +6,4 @@ "description" : "dummy", "deadline" : "01/01/2022" } ] -} \ No newline at end of file +} diff --git a/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json b/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json index 3a4ac63c303..8115d138a2c 100644 --- a/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json +++ b/src/test/data/JsonTaskListStorageTest/invalidTaskTaskList.json @@ -3,4 +3,4 @@ "description" : null, "deadline" : "01/01/2022" } ] -} \ No newline at end of file +} From 9fe9c640cfa8f8250f70bc620322ed8ad14d0d75 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 29 Mar 2022 15:36:37 +0800 Subject: [PATCH 067/140] Remove unused parameter in method signature --- .../java/seedu/address/logic/commands/UpdateTaskCommand.java | 2 +- src/main/java/seedu/address/model/Model.java | 2 +- src/main/java/seedu/address/model/ModelManager.java | 2 +- src/test/java/seedu/address/logic/commands/AddCommandTest.java | 2 +- .../java/seedu/address/logic/commands/AddTaskCommandTest.java | 2 +- .../seedu/address/logic/commands/DeleteTaskCommandTest.java | 2 +- .../java/seedu/address/logic/commands/FindTaskCommandTest.java | 2 +- .../java/seedu/address/logic/commands/ViewTaskCommandTest.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java index b6f8c791f54..7152b08dbed 100644 --- a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -59,7 +59,7 @@ public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_DUPLICATE_TASK); } - model.updateTask(taskToUpdate, updatedTask, taskId); + model.updateTask(updatedTask, taskId); return new CommandResult(String.format(MESSAGE_UPDATE_TASK_SUCCESS, updatedTask)); } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index f02ef5ee7a3..78ac4b39c07 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -102,5 +102,5 @@ public interface Model { String viewTask(); - void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId); + void updateTask(Task updatedTask, Integer taskId); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 0ba10ff073a..03fc5ead56f 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -191,7 +191,7 @@ public String viewTask() { //=========== Update Task =============== @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { taskList.deleteTask(taskId); taskList.addTask(updatedTask, taskId); } diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 48d07e98cf3..535173da52a 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -181,7 +181,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 7daf5d52444..330bbff6286 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -154,7 +154,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index adf3016017e..b45848d1843 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -187,7 +187,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 2b0b4222f86..f6713486b43 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -186,7 +186,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index 1e8ef6fe6cf..a0e42c5f3fe 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -147,7 +147,7 @@ public String viewTask() { } @Override - public void updateTask(Task taskToUpdate, Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) { throw new AssertionError("This method should not be called."); } } From e031745323fd45e8ae187d3e4db37a6dc5c6fb0b Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 29 Mar 2022 16:19:30 +0800 Subject: [PATCH 068/140] Update ModelManagerTest - Add test for setTaskListFilePath --- .../java/seedu/address/model/ModelManagerTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 032bcbd40b0..0965cd0ea5e 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -72,6 +72,18 @@ public void setAddressBookFilePath_validPath_setsAddressBookFilePath() { assertEquals(path, modelManager.getAddressBookFilePath()); } + @Test + public void setTaskListFilePath_nullPath_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> modelManager.setTaskListFilePath(null)); + } + + @Test + public void setTaskListFilePath_validPath_setsAddressBookFilePath() { + Path path = Paths.get("task/list/file/path"); + modelManager.setTaskListFilePath(path); + assertEquals(path, modelManager.getTaskListFilePath()); + } + @Test public void hasPerson_nullPerson_throwsNullPointerException() { assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null)); From dd1eba68e5956e28d3ff6f673d275661fea45e51 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 29 Mar 2022 16:37:11 +0800 Subject: [PATCH 069/140] Update Model.java --- src/main/java/seedu/address/model/Model.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 9933cb066cf..60d1d541dc6 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -104,9 +104,9 @@ public interface Model { Path getTaskListFilePath(); - + void setTaskListFilePath(Path taskListFilePath); - + ReadOnlyTaskList getReadOnlyTaskList(); void updateTask(Task updatedTask, Integer taskId); From 1478f147b4323dc7fe5951f51b99dd2013bfacb9 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 29 Mar 2022 16:38:28 +0800 Subject: [PATCH 070/140] Update TaskList.java --- src/main/java/seedu/address/model/TaskList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 490557344d7..2f13cef3dbf 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -131,7 +131,7 @@ private String getOutput(ArrayList list) { } return sb.toString(); } - + /** * Provides the task in the corresponding index * @param taskId task id of the task to be retrieved @@ -140,7 +140,7 @@ private String getOutput(ArrayList list) { public Task getTask(Integer taskId) { return taskList.get(taskId - 1); // to convert to zero-based } - + @Override public ObservableList getObservableTaskList() { ObservableList taskObservableList = FXCollections.observableArrayList(taskList); From cf7fa66b8aec307fd99d8492284399f2e0f59968 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 29 Mar 2022 16:48:09 +0800 Subject: [PATCH 071/140] Fix bracket issues --- src/test/java/seedu/address/logic/commands/AddCommandTest.java | 2 ++ .../java/seedu/address/logic/commands/AddTaskCommandTest.java | 2 ++ .../seedu/address/logic/commands/DeleteTaskCommandTest.java | 2 ++ .../java/seedu/address/logic/commands/FindTaskCommandTest.java | 2 ++ .../java/seedu/address/logic/commands/ViewTaskCommandTest.java | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 21797357e8f..1a70689bc0f 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -193,6 +193,8 @@ public void setTaskListFilePath(Path taskListFilePath) { @Override public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateTask(Task updatedTask, Integer taskId) { diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 53109066e90..9a4f7941cba 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -166,6 +166,8 @@ public void setTaskListFilePath(Path taskListFilePath) { @Override public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateTask(Task updatedTask, Integer taskId) { diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index d23e3ccccbc..e1e913034c8 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -200,6 +200,8 @@ public void setTaskListFilePath(Path taskListFilePath) { @Override public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateTask(Task updatedTask, Integer taskId) { diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index a6cfec09782..695a395388c 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -199,6 +199,8 @@ public void setTaskListFilePath(Path taskListFilePath) { @Override public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateTask(Task updatedTask, Integer taskId) { diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index ec14935b091..ba48ef0f9e1 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -159,6 +159,8 @@ public void setTaskListFilePath(Path taskListFilePath) { @Override public ReadOnlyTaskList getReadOnlyTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void updateTask(Task updatedTask, Integer taskId) { From 3e212d3babb2d8fa505d4f8736f6cac13d45b043 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 29 Mar 2022 19:47:28 +0800 Subject: [PATCH 072/140] Improve coverage by add tests for UpdateTaskCommand and UpdateTaskCommandParser --- .../logic/commands/UpdateTaskCommand.java | 10 +- .../logic/commands/CommandTestUtil.java | 15 ++ .../logic/commands/UpdateTaskCommandTest.java | 140 ++++++++++++++++++ .../parser/UpdateTaskCommandParserTest.java | 90 +++++++++++ 4 files changed, 249 insertions(+), 6 deletions(-) create mode 100644 src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java create mode 100644 src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java index 7152b08dbed..92dd2e919d8 100644 --- a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -9,6 +9,8 @@ import seedu.address.model.TaskList; import seedu.address.model.task.Task; +import java.util.Optional; + public class UpdateTaskCommand extends Command { public static final String COMMAND_WORD = "updt"; @@ -68,7 +70,7 @@ public CommandResult execute(Model model) throws CommandException { * Creates and returns a {@code Task} with the details of {@code taskToEdit} * edited with {@code updateTaskDescriptor}. */ - private static Task createUpdatedTask(Task taskToUpdate, UpdateTaskDescriptor updateTaskDescriptor) { + public static Task createUpdatedTask(Task taskToUpdate, UpdateTaskDescriptor updateTaskDescriptor) { assert taskToUpdate != null; String updatedDescription = ""; @@ -86,11 +88,7 @@ private static Task createUpdatedTask(Task taskToUpdate, UpdateTaskDescriptor up updatedDeadline = updateTaskDescriptor.getDeadline(); } - if (updatedDeadline == null) { - return new Task(updatedDescription, "No deadline set"); - } else { - return new Task(updatedDescription, updatedDeadline); - } + return new Task(updatedDescription, updatedDeadline); } @Override diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 643a1d08069..d7a5e402830 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -7,6 +7,10 @@ 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; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; + + import static seedu.address.testutil.Assert.assertThrows; import java.util.ArrayList; @@ -37,6 +41,17 @@ public class CommandTestUtil { public static final String VALID_TAG_HUSBAND = "husband"; public static final String VALID_TAG_FRIEND = "friend"; + public static final String VALID_DESCRIPTION_SWIMMING = "Swimming Lesson"; + public static final String VALID_DESCRIPTION_RUNNING = "Running Lesson"; + public static final String VALID_DEADLINE_MARCH = "03/03/2022"; + public static final String VALID_DEADLINE_OCT = "10/10/2022"; + + public static final String DESC_SWIMMING = " " + PREFIX_ADD_TASK_DESCRIPTION + VALID_DESCRIPTION_SWIMMING; + public static final String DEADLINE_SWIMMING = " " + PREFIX_ADD_TASK_DEADLINE + VALID_DEADLINE_MARCH; + + public static final String INVALID_DEADLINE_YEAR = " " + PREFIX_ADD_TASK_DEADLINE + "2022"; // Wrong format + public static final String INVALID_DEADLINE_MONTH = " " + PREFIX_ADD_TASK_DEADLINE + "03/2022"; // Wrong format + public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY; public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB; public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY; diff --git a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java new file mode 100644 index 00000000000..642ebe644ee --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java @@ -0,0 +1,140 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY; +import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static seedu.address.testutil.TypicalTask.getTypicalTaskList; +import org.junit.jupiter.api.Test; +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.model.AddressBook; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; +import seedu.address.model.task.Task; +import seedu.address.testutil.EditPersonDescriptorBuilder; +import seedu.address.testutil.PersonBuilder; + +public class UpdateTaskCommandTest { + private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); + + @Test + public void execute_allFieldsSpecifiedUnfilteredList_success() { + Task updatedTask = new Task("test", "03/03/2022"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(updatedTask.getDescription()); + descriptor.setDeadline(updatedTask.getDeadline()); + UpdateTaskCommand updateTaskCommand = new UpdateTaskCommand(1, descriptor); + + String expectedMessage = String.format(UpdateTaskCommand.MESSAGE_UPDATE_TASK_SUCCESS, updatedTask); + + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs(), + model.getTaskList()); + expectedModel.updateTask(updatedTask, 1); + + assertCommandSuccess(updateTaskCommand, model, expectedMessage, expectedModel); + } + + @Test + public void createTask_descriptorWithoutDeadline() { + Task updatedTask = new Task("test","03/03/2022"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(updatedTask.getDescription()); + Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); + assertTrue(newTaskCreated.getDeadline().equals(updatedTask.getDeadline())); + } + + @Test + public void createTask_descriptorWithoutDescription() { + Task updatedTask = new Task("test","03/03/2022"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDeadline(updatedTask.getDeadline()); + Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); + assertTrue(newTaskCreated.getDescription().equals(updatedTask.getDescription())); + } + + @Test + public void createTaskWithoutDeadline_descriptorWithoutDeadline() { + Task updatedTask = new Task("test","No deadline set"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(updatedTask.getDescription()); + Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); + assertTrue(newTaskCreated.getDeadline().equals("No deadline set")); + } + + @Test + public void execute_updateDuplicateTask_failure() { + Task updatedTask = new Task("test", "03/03/2022"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(updatedTask.getDescription()); + descriptor.setDeadline(updatedTask.getDeadline()); + UpdateTaskCommand updateTaskCommand = new UpdateTaskCommand(1, descriptor); + model.updateTask(updatedTask, 1); + model.updateTask(updatedTask, 1); // throw duplicate task error + + assertCommandFailure(updateTaskCommand, model, "This task already exists in the task list."); + } + + @Test + public void execute_invalidPersonIndexUnfilteredList_failure() { + Integer outOfBoundIndex = model.getTaskList().size() + 1; + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription("test"); + descriptor.setDeadline("03/03/2022"); + UpdateTaskCommand updateTaskCommand = new UpdateTaskCommand(outOfBoundIndex, descriptor); + + assertCommandFailure(updateTaskCommand, model, "The task id provided is invalid"); + } + + @Test + public void equals() { + Task updatedTask = new Task("test", "03/03/2022"); + Task differentTask = new Task("differentTest", "05/05/2022"); + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(updatedTask.getDescription()); + descriptor.setDeadline(updatedTask.getDeadline()); + final UpdateTaskCommand standardCommand = new UpdateTaskCommand(1, descriptor); + + // same values -> returns true + UpdateTaskCommand.UpdateTaskDescriptor copyDescriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + copyDescriptor.setDescription(updatedTask.getDescription()); + copyDescriptor.setDeadline(updatedTask.getDeadline()); + UpdateTaskCommand commandWithSameValues = new UpdateTaskCommand(1, copyDescriptor); + assertTrue(standardCommand.equals(commandWithSameValues)); + + // same object -> returns true + assertTrue(standardCommand.equals(standardCommand)); + assertTrue(descriptor.equals(descriptor)); + + // null -> returns false + assertFalse(standardCommand.equals(null)); + + // different types -> returns false + assertFalse(standardCommand.equals(new ClearCommand())); + assertFalse(descriptor.equals(new ClearCommand())); + + // different index -> returns false + assertFalse(standardCommand.equals(new UpdateTaskCommand(2, descriptor))); + + UpdateTaskCommand.UpdateTaskDescriptor differentDescriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(differentTask.getDescription()); + descriptor.setDeadline(differentTask.getDeadline()); + + // different descriptor -> returns false + assertFalse(standardCommand.equals(new UpdateTaskCommand(1, differentDescriptor))); + + } + + +} diff --git a/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java new file mode 100644 index 00000000000..f246ff6d3d2 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java @@ -0,0 +1,90 @@ +package seedu.address.logic.parser; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.commands.CommandTestUtil.DEADLINE_SWIMMING; +import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_MARCH; +import static seedu.address.logic.commands.CommandTestUtil.VALID_DESCRIPTION_SWIMMING; +import static seedu.address.logic.commands.CommandTestUtil.DESC_SWIMMING; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_YEAR; +import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_MONTH; + +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.UpdateTaskCommand; + +public class UpdateTaskCommandParserTest { + + private static final String MESSAGE_INVALID_FORMAT = + String.format(MESSAGE_INVALID_COMMAND_FORMAT, UpdateTaskCommand.MESSAGE_USAGE); + + private UpdateTaskCommandParser parser = new UpdateTaskCommandParser(); + + @Test + public void parse_missingParts_failure() { + // no taskId specified + assertParseFailure(parser, VALID_DESCRIPTION_SWIMMING, MESSAGE_INVALID_FORMAT); + + // no field specified + assertParseFailure(parser, "1", MESSAGE_INVALID_FORMAT); + + // no taskId and no field specified + assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_invalidPreamble_failure() { + // negative index + assertParseFailure(parser, "-5" + DESC_SWIMMING, MESSAGE_INVALID_FORMAT); + + // zero index + assertParseFailure(parser, "0" + DESC_SWIMMING, MESSAGE_INVALID_FORMAT); + + // invalid arguments being parsed as preamble + assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT); + + // invalid prefix being parsed as preamble + assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_invalidValue_failure() { + assertParseFailure(parser, "1" + INVALID_DEADLINE_YEAR, MESSAGE_INVALID_FORMAT); // invalid deadline + assertParseFailure(parser, "1" + INVALID_DEADLINE_MONTH, MESSAGE_INVALID_FORMAT); // invalid deadline + assertParseFailure(parser, "1" + " d/", MESSAGE_INVALID_FORMAT); // empty description + assertParseFailure(parser, "1" + " t/", MESSAGE_INVALID_FORMAT); // empty deadline + + // valid description followed by invalid deadline + assertParseFailure(parser, "1" + DESC_SWIMMING + INVALID_DEADLINE_YEAR, MESSAGE_INVALID_FORMAT); + + // invalid description followed by valid deadline. + assertParseFailure(parser, "1" + " d/" + DEADLINE_SWIMMING, MESSAGE_INVALID_FORMAT); + + // multiple invalid values + assertParseFailure(parser, "1" + " d/" + INVALID_DEADLINE_YEAR, MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_allFieldsSpecified_success() { + Integer targetTaskId = 1; + String userInput = targetTaskId + DESC_SWIMMING + DEADLINE_SWIMMING; + + UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); + descriptor.setDescription(VALID_DESCRIPTION_SWIMMING); + descriptor.setDeadline(VALID_DEADLINE_MARCH); + + UpdateTaskCommand expectedCommand = new UpdateTaskCommand(targetTaskId, descriptor); + + assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_multipleRepeatedFields_failure() { + Integer targetTaskId = 1; + String userInput = targetTaskId + DESC_SWIMMING + DESC_SWIMMING; + + assertParseFailure(parser, userInput, MESSAGE_INVALID_FORMAT); + } + +} From 60e27259b8c8f4d6dc9e2aac3b2673760f9a2592 Mon Sep 17 00:00:00 2001 From: ivorcmx Date: Tue, 29 Mar 2022 19:58:30 +0800 Subject: [PATCH 073/140] Fix checkstyle errors --- .../logic/commands/UpdateTaskCommand.java | 1 - .../logic/commands/CommandTestUtil.java | 8 ++----- .../logic/commands/UpdateTaskCommandTest.java | 21 +++++-------------- .../parser/UpdateTaskCommandParserTest.java | 8 +++---- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java index 92dd2e919d8..24e6cf930bb 100644 --- a/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java +++ b/src/main/java/seedu/address/logic/commands/UpdateTaskCommand.java @@ -9,7 +9,6 @@ import seedu.address.model.TaskList; import seedu.address.model.task.Task; -import java.util.Optional; public class UpdateTaskCommand extends Command { public static final String COMMAND_WORD = "updt"; diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index d7a5e402830..845c8cd52f2 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -3,14 +3,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; 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; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DESCRIPTION; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TASK_DEADLINE; - - import static seedu.address.testutil.Assert.assertThrows; import java.util.ArrayList; @@ -42,9 +40,7 @@ public class CommandTestUtil { public static final String VALID_TAG_FRIEND = "friend"; public static final String VALID_DESCRIPTION_SWIMMING = "Swimming Lesson"; - public static final String VALID_DESCRIPTION_RUNNING = "Running Lesson"; public static final String VALID_DEADLINE_MARCH = "03/03/2022"; - public static final String VALID_DEADLINE_OCT = "10/10/2022"; public static final String DESC_SWIMMING = " " + PREFIX_ADD_TASK_DESCRIPTION + VALID_DESCRIPTION_SWIMMING; public static final String DEADLINE_SWIMMING = " " + PREFIX_ADD_TASK_DEADLINE + VALID_DEADLINE_MARCH; diff --git a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java index 642ebe644ee..f138985f6c5 100644 --- a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java @@ -2,29 +2,18 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import static seedu.address.testutil.TypicalTask.getTypicalTaskList; + import org.junit.jupiter.api.Test; -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; + import seedu.address.model.AddressBook; import seedu.address.model.Model; import seedu.address.model.ModelManager; import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; import seedu.address.model.task.Task; -import seedu.address.testutil.EditPersonDescriptorBuilder; -import seedu.address.testutil.PersonBuilder; public class UpdateTaskCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @@ -48,7 +37,7 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() { @Test public void createTask_descriptorWithoutDeadline() { - Task updatedTask = new Task("test","03/03/2022"); + Task updatedTask = new Task("test", "03/03/2022"); UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); descriptor.setDescription(updatedTask.getDescription()); Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); @@ -57,7 +46,7 @@ public void createTask_descriptorWithoutDeadline() { @Test public void createTask_descriptorWithoutDescription() { - Task updatedTask = new Task("test","03/03/2022"); + Task updatedTask = new Task("test", "03/03/2022"); UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); descriptor.setDeadline(updatedTask.getDeadline()); Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); @@ -66,7 +55,7 @@ public void createTask_descriptorWithoutDescription() { @Test public void createTaskWithoutDeadline_descriptorWithoutDeadline() { - Task updatedTask = new Task("test","No deadline set"); + Task updatedTask = new Task("test", "No deadline set"); UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); descriptor.setDescription(updatedTask.getDescription()); Task newTaskCreated = UpdateTaskCommand.createUpdatedTask(updatedTask, descriptor); diff --git a/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java b/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java index f246ff6d3d2..d7679a78cb2 100644 --- a/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/UpdateTaskCommandParserTest.java @@ -2,16 +2,16 @@ import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.commands.CommandTestUtil.DEADLINE_SWIMMING; -import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_MARCH; -import static seedu.address.logic.commands.CommandTestUtil.VALID_DESCRIPTION_SWIMMING; import static seedu.address.logic.commands.CommandTestUtil.DESC_SWIMMING; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_YEAR; import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_MONTH; - +import static seedu.address.logic.commands.CommandTestUtil.INVALID_DEADLINE_YEAR; +import static seedu.address.logic.commands.CommandTestUtil.VALID_DEADLINE_MARCH; +import static seedu.address.logic.commands.CommandTestUtil.VALID_DESCRIPTION_SWIMMING; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; import org.junit.jupiter.api.Test; + import seedu.address.logic.commands.UpdateTaskCommand; public class UpdateTaskCommandParserTest { From 4a2207ad15f8493b78e99e10990d0b0b7596dc18 Mon Sep 17 00:00:00 2001 From: putaojuice <33406416+putaojuice@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:20:31 +0800 Subject: [PATCH 074/140] Update PPP and UG --- docs/UserGuide.md | 15 +-------------- docs/team/putaojuice.md | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fa225b0086d..b2bd76aee8a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,15 +13,12 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona - Add task - Delete task - Update task - - Add a label to a task - View all tasks and their deadlines - Contact Management - Add contact - Delete contact - Update contact - View all contacts - - Reminder - - Remind the user of upcoming tasks - Exit the app - FAQ - CLI Summary @@ -102,14 +99,6 @@ Format: `upd t t /DEADLINE` Example: `upd t t /2022 03 10 12pm` -### Feature - Label a task: `lab t ` - -Label a task based on a specific tag, where `` is the ID of the task. - -Format: `label t tag` - -Example: `label t 3 important` - ### Feature - Find tasks: `findt KEYWORD` Locating tasks which match any of given keywords. @@ -217,11 +206,9 @@ data of your previous NUScheduler home folder. | **upd t d ** | `upd t d   /DESCRIPTION`
e.g., `upd t d 3 /Buy groceries` | | **upd t t ** | `upd t t /DEADLINE`
e.g.,`upd t t /2022 03 10 12pm` | | **findt KEYWORD** | `findt `
e.g., `findt lessons` | -| **lab t ** | `label t tag`
e.g., `label t 3 important` | -| **view t** | `view t` | +| **viewt** | `view t` | | **add c** | `add c /NAME /EMAIL /TELEGRAM [/TAG]`
e.g., `add c /Betsy Crow /betsycrow@example.com /betsyc /Group Member` | | **del c ** | `del c `
e.g., `del c 3` | | **upd c ** | `upd c /NAME /EMAIL /TELEGRAM [/TAG] `
e.g., `upd c /John Doe  /johndoe@example.com /johntele 23` | | **view c** | `view c [to] [t] [/TAG]`
e.g., `view c` | -| **remind** | `remind []`
e.g., `remind 10` | | **exit** | `exit` | diff --git a/docs/team/putaojuice.md b/docs/team/putaojuice.md index e61a893ba4d..467e10bc831 100644 --- a/docs/team/putaojuice.md +++ b/docs/team/putaojuice.md @@ -9,10 +9,10 @@ If you can type fast, NUScheduler can schedule your tasks faster than traditiona Given below are my contributions to the project. -* **New Feature**: Implemented `AddTask` command. +* **New Feature**: Implemented `AddTask` command ([#26](https://github.com/AY2122S2-CS2103-F11-4/tp/pull/26)). * What it does: Allow the user to add a task to the application with description and deadline (optional) * Justification: Our target audience is year 1 computing students. It helps them to keep track of their assignments - and any other daily tasks. +and any other daily tasks. * **Classes created**: * `AddTaskCommand` * `AddTaskCommandParser` @@ -24,12 +24,35 @@ Given below are my contributions to the project. * `Task` and `TaskList` classes are created to capture the information of tasks and store them as an `ArrayList` in `ModelManager`. -* **Code contributed**: [RepoSense link (to be added soon)]() +* **New Feature**: Implemented `TaskListStorage` ([#74](https://github.com/AY2122S2-CS2103-F11-4/tp/pull/74)). + * What it does: The system will write the task list to user's local folder in Json format whenever there is a change +in the task list. The system will read from the saved task list from user's local folder in Json format when starting up +to load the stored task list from the last access. + * Justification: This feature allows the user to save their task list and continue where it was left from. + * **Classes created**: + * `ReadOnlyTaskList` + * `JsonAdaptedTask` + * `JsonSerializableTaskList` + * `JsonTaskListStorage` + * `TaskListStorage` + * **Tests written**: + * `JsonAdaptedTaskTest` + * `JsonSerializableTaskListTest` + * `JsonTaskListStorageTest` + * `TypicalTask` + * **Additional info**: + * This feature requires a good understand of how the application is designed and involves modification to +`Logic`, `Model` and `Storage` + +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2122s2.github.io/tp-dashboard/?search=putaojuice&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2022-02-18&tabOpen=true&tabType=authorship&tabAuthor=putaojuice&tabRepo=AY2122S2-CS2103-F11-4%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false) * **Project management**: - * Managed release `v1.1`, `v1.2`. + * Managed release `v1.1`, `v1.2`, `v1.3`. * Organised weekly project meeting and set up weekly milestone. * Reviewed pull requests. + * Wrap up every milestone. + * Released `Trial v1.3` ([#61](https://github.com/AY2122S2-CS2103-F11-4/tp/pull/61)). + * Complete any administrative matters for the team. * **Enhancements to existing features**: * to be added soon @@ -41,11 +64,13 @@ Given below are my contributions to the project. * Added various non-functional requirement in the developer guide. * Contribute to glossary in the developer guide. * Added MSS for `AddTask`. + * Added information about the implementation of the `AddTask` command ([#60](https://github.com/AY2122S2-CS2103-F11-4/tp/pull/60)) + * Added 2 UML diagrams to aid the explanations * **Community**: - * to be added soon + * Participate in forum ([#240](https://github.com/nus-cs2103-AY2122S2/forum/issues/240)) * **Tools**: - * to be added soon - - + * Set up the team's Github group and repo. + * Added CodeCov integration to the repo. + * Enabled assertions for the project ([#61](https://github.com/AY2122S2-CS2103-F11-4/tp/pull/61)). From 5cc9d068ad267d6b57ebfb2b3d27d2eabb6350cd Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 30 Mar 2022 01:49:08 +0800 Subject: [PATCH 075/140] Update Ui to show TaskList in Gui --- src/main/java/seedu/address/logic/Logic.java | 4 + .../seedu/address/logic/LogicManager.java | 6 + src/main/java/seedu/address/model/Model.java | 14 ++- .../seedu/address/model/ModelManager.java | 28 ++++- .../address/model/ReadOnlyAddressBook.java | 2 +- .../java/seedu/address/model/TaskList.java | 24 +++- .../address/model/task/UniqueTaskList.java | 105 ++++++++++++++++++ .../java/seedu/address/ui/MainWindow.java | 6 + src/main/java/seedu/address/ui/TaskCard.java | 61 ++++++++++ .../java/seedu/address/ui/TaskListPanel.java | 45 ++++++++ src/main/resources/view/MainWindow.fxml | 8 +- src/main/resources/view/TaskCard.fxml | 32 ++++++ src/main/resources/view/TaskListPanel.fxml | 8 ++ .../logic/commands/AddCommandTest.java | 9 ++ .../logic/commands/AddTaskCommandTest.java | 10 ++ .../logic/commands/DeleteTaskCommandTest.java | 10 ++ .../logic/commands/FindTaskCommandTest.java | 10 ++ .../logic/commands/ViewTaskCommandTest.java | 10 ++ 18 files changed, 379 insertions(+), 13 deletions(-) create mode 100644 src/main/java/seedu/address/model/task/UniqueTaskList.java create mode 100644 src/main/java/seedu/address/ui/TaskCard.java create mode 100644 src/main/java/seedu/address/ui/TaskListPanel.java create mode 100644 src/main/resources/view/TaskCard.fxml create mode 100644 src/main/resources/view/TaskListPanel.fxml diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..5e1f29acc2b 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -9,6 +9,7 @@ import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.person.Person; +import seedu.address.model.task.Task; /** * API of the Logic component @@ -33,6 +34,9 @@ public interface Logic { /** Returns an unmodifiable view of the filtered list of persons */ ObservableList getFilteredPersonList(); + /** Returns an unmodifiable view of the filtered list of tasks */ + ObservableList getFilteredTaskList(); + /** * Returns the user prefs' address book file path. */ diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index d19ea63cf72..9dad16689a6 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -15,6 +15,7 @@ import seedu.address.model.Model; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.person.Person; +import seedu.address.model.task.Task; import seedu.address.storage.Storage; /** @@ -66,6 +67,11 @@ public ObservableList getFilteredPersonList() { return model.getFilteredPersonList(); } + @Override + public ObservableList getFilteredTaskList() { + return model.getFilteredTaskList(); + } + @Override public Path getAddressBookFilePath() { return model.getAddressBookFilePath(); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 60d1d541dc6..86cc425406f 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -5,6 +5,7 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.person.Person; import seedu.address.model.task.Task; @@ -86,9 +87,18 @@ public interface Model { */ void updateFilteredPersonList(Predicate predicate); + /** + * Updates the filter of the filtered person list to filter by the given {@code predicate}. + * @throws NullPointerException if {@code predicate} is null. + */ + void updateFilteredTaskList(Predicate predicate); + + /** Returns an unmodifiable view of the filtered tasks list */ + ObservableList getFilteredTaskList(); + void addTask(Task task); - void addTask(Task task, Integer taskId); + void addTask(Task task, Integer taskId) throws CommandException; TaskList getTaskList(); @@ -109,6 +119,6 @@ public interface Model { ReadOnlyTaskList getReadOnlyTaskList(); - void updateTask(Task updatedTask, Integer taskId); + void updateTask(Task updatedTask, Integer taskId) throws CommandException; } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 7288dc937f8..5a4d3adf9a1 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -11,6 +11,7 @@ import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.person.Person; import seedu.address.model.task.Task; @@ -23,7 +24,7 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; private final FilteredList filteredPersons; - + private final FilteredList filteredTasks; private final TaskList taskList; /** @@ -37,8 +38,8 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); - this.taskList = new TaskList(taskList); + filteredTasks = new FilteredList<>(this.taskList.getObservableTaskList()); } public ModelManager() { @@ -160,18 +161,35 @@ public boolean equals(Object obj) { ModelManager other = (ModelManager) obj; return addressBook.equals(other.addressBook) && userPrefs.equals(other.userPrefs) - && filteredPersons.equals(other.filteredPersons); + && filteredPersons.equals(other.filteredPersons) + && filteredTasks.equals(other.filteredTasks); + } + //=========== Filtered Task List Accessors ============================================================= + /** + * Returns an unmodifiable view of the list of {@code Task} backed by the internal list of + * {@code versionedAddressBook} + * @return filteredTasks + */ + @Override + public ObservableList getFilteredTaskList() { + return filteredTasks; } + @Override + public void updateFilteredTaskList(Predicate predicate) { + requireNonNull(predicate); + filteredTasks.setPredicate(predicate); + } //=========== TaskList ================================================================================== @Override public void addTask(Task task) { taskList.addTask(task); + filteredTasks.setPredicate(unused -> true); } @Override - public void addTask(Task task, Integer taskId) { + public void addTask(Task task, Integer taskId) throws CommandException { taskList.addTask(task, taskId); } @@ -206,7 +224,7 @@ public String viewTask() { //=========== Update Task =============== @Override - public void updateTask(Task updatedTask, Integer taskId) { + public void updateTask(Task updatedTask, Integer taskId) throws CommandException { taskList.deleteTask(taskId); taskList.addTask(updatedTask, taskId); } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 6ddc2cd9a29..f0673ed3838 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -13,5 +13,5 @@ public interface ReadOnlyAddressBook { * This list will not contain any duplicate persons. */ ObservableList getPersonList(); - } + diff --git a/src/main/java/seedu/address/model/TaskList.java b/src/main/java/seedu/address/model/TaskList.java index 2f13cef3dbf..756acb0336c 100644 --- a/src/main/java/seedu/address/model/TaskList.java +++ b/src/main/java/seedu/address/model/TaskList.java @@ -5,12 +5,14 @@ import java.util.ArrayList; import java.util.List; -import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.task.Task; +import seedu.address.model.task.UniqueTaskList; public class TaskList implements ReadOnlyTaskList { private final ArrayList taskList; + private final UniqueTaskList uniqueTaskList; /* * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication @@ -21,6 +23,7 @@ public class TaskList implements ReadOnlyTaskList { */ { taskList = new ArrayList<>(); + uniqueTaskList = new UniqueTaskList(); } public TaskList() {} @@ -43,7 +46,9 @@ public void resetData(ReadOnlyTaskList newData) { } public void setTaskList(List tasks) { + requireNonNull(tasks); this.taskList.addAll(tasks); + this.uniqueTaskList.addAll(tasks); } /** @@ -54,6 +59,7 @@ public void setTaskList(List tasks) { public void addTask(Task task) { requireNonNull(task); this.taskList.add(task); + this.uniqueTaskList.addTask(task); } /** @@ -62,7 +68,8 @@ public void addTask(Task task) { * @param task the Task to be added which must not be null * @param taskId the location to be added in which must not be null */ - public void addTask(Task task, Integer taskId) { + public void addTask(Task task, Integer taskId) throws CommandException { + uniqueTaskList.addTask(task, taskId); //throws an exception if adding duplicate task requireNonNull(task); requireNonNull(taskId); this.taskList.add(taskId - 1, task); // to convert to zero-based indexing @@ -81,8 +88,14 @@ public int size() { return this.taskList.size(); } + /** + * Deletes a task from the tasklist in the specified index. + * + * @param taskNumber the index of the task to be deleted + */ public void deleteTask(Integer taskNumber) { taskList.remove(taskNumber - 1); // to convert to zero-based indexing + uniqueTaskList.deleteTask(taskNumber); } /** @@ -141,10 +154,13 @@ public Task getTask(Integer taskId) { return taskList.get(taskId - 1); // to convert to zero-based } + /** + * Retrieves the observable list of tasks + * @return observable list of tasks + */ @Override public ObservableList getObservableTaskList() { - ObservableList taskObservableList = FXCollections.observableArrayList(taskList); - return taskObservableList; + return uniqueTaskList.asUnmodifiableObservableList(); } } diff --git a/src/main/java/seedu/address/model/task/UniqueTaskList.java b/src/main/java/seedu/address/model/task/UniqueTaskList.java new file mode 100644 index 00000000000..4be27564e30 --- /dev/null +++ b/src/main/java/seedu/address/model/task/UniqueTaskList.java @@ -0,0 +1,105 @@ +package seedu.address.model.task; + +import static java.util.Objects.requireNonNull; + +import java.util.Iterator; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.logic.commands.exceptions.CommandException; + +/** + * A list of tasks that enforces uniqueness between its elements and does not allow nulls. + * A person is considered unique by comparing using {@code Task#isSameTask(Task)}. As such, adding and updating of + * persons uses Task#isSameTask(Task) for equality so as to ensure that the task being added or updated is + * unique in terms of identity in the UniquePTaskList. However, the removal of a person uses Task#equals(Object) so + * as to ensure that the task with exactly the same fields will be removed. + * + * Supports a minimal set of list operations. + * + */ +public class UniqueTaskList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent task as the given argument. + */ + public boolean contains(Task toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSameTask); + } + + /** + * Add a task to the taskList. + * + * @param task the Task to be added which must not be null + */ + public void addTask(Task task) { + requireNonNull(task); + this.internalList.add(task); + } + + /** + * Adds a task to the list at a specific index. + * The task must not already exist in the list. + * + * @param toAdd the Task to be added which must not be null + * @param taskId index of the list the task is to be added + */ + + public void addTask(Task toAdd, Integer taskId) throws CommandException { + requireNonNull(toAdd); + requireNonNull(taskId); + if (contains(toAdd)) { + throw new CommandException("Duplicate Task received"); + } + internalList.add(taskId - 1, toAdd); // to convert to zero-based indexing + } + + /** + * Sets the observable list of tasks from storage. + */ + public void addAll(List tasks) { + requireNonNull(tasks); + this.internalList.setAll(tasks); + } + + /** + * Removes the equivalent task from the list. + * The task must exist in the list. + */ + + public void deleteTask(Integer taskNumber) { + requireNonNull(taskNumber); + internalList.remove(taskNumber - 1); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UniqueTaskList // instanceof handles nulls + && internalList.equals(((UniqueTaskList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 9106c3aa6e5..55cc6bfe2bc 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -34,6 +34,7 @@ public class MainWindow extends UiPart { private PersonListPanel personListPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; + private TaskListPanel taskListPanel; @FXML private StackPane commandBoxPlaceholder; @@ -44,6 +45,9 @@ public class MainWindow extends UiPart { @FXML private StackPane personListPanelPlaceholder; + @FXML + private StackPane taskListPanelPlaceholder; + @FXML private StackPane resultDisplayPlaceholder; @@ -113,6 +117,8 @@ void fillInnerParts() { personListPanel = new PersonListPanel(logic.getFilteredPersonList()); personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); + taskListPanel = new TaskListPanel(logic.getFilteredTaskList()); + taskListPanelPlaceholder.getChildren().add(taskListPanel.getRoot()); resultDisplay = new ResultDisplay(); resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); diff --git a/src/main/java/seedu/address/ui/TaskCard.java b/src/main/java/seedu/address/ui/TaskCard.java new file mode 100644 index 00000000000..76e5f1f8998 --- /dev/null +++ b/src/main/java/seedu/address/ui/TaskCard.java @@ -0,0 +1,61 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import seedu.address.model.task.Task; + +public class TaskCard extends UiPart { + private static final String FXML = "TaskCard.fxml"; + + /** + * 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 + * or an exception will be thrown by JavaFX during runtime. + * + * @see
The issue on AddressBook level 4 + */ + + public final Task task; + + @FXML + private HBox cardPane; + @FXML + private Label taskDescription; + @FXML + private Label taskDeadline; + @FXML + private Label taskId; + + /** + * Creates a {@code TaskCode} with the given {@code Task} and index to display. + */ + public TaskCard(Task task, int displayedIndex) { + super(FXML); + this.task = task; + taskId.setText(displayedIndex + ". "); + //taskTitle.setText("Tasks:"); + taskDescription.setText(task.getDescription()); + taskDeadline.setText(task.getDeadline()); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof TaskCard)) { + return false; + } + + // state check + TaskCard card = (TaskCard) other; + return taskId.getText().equals(card.taskId.getText()) + && task.equals(card.task); + } +} + diff --git a/src/main/java/seedu/address/ui/TaskListPanel.java b/src/main/java/seedu/address/ui/TaskListPanel.java new file mode 100644 index 00000000000..5cb02d1e32f --- /dev/null +++ b/src/main/java/seedu/address/ui/TaskListPanel.java @@ -0,0 +1,45 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.task.Task; + +public class TaskListPanel extends UiPart { + private static final String FXML = "TaskListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); + + @FXML + private ListView taskListView; + + /** + * Creates a {@code PersonListPanel} with the given {@code ObservableList}. + */ + public TaskListPanel(ObservableList taskList) { + super(FXML); + taskListView.setItems(taskList); + taskListView.setCellFactory(listView -> new TaskListPanel.TaskListViewCell()); + } + + /** + * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. + */ + class TaskListViewCell extends ListCell { + @Override + protected void updateItem(Task task, boolean empty) { + super.updateItem(task, empty); + + if (empty || task == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new TaskCard(task, getIndex() + 1).getRoot()); + } + } + } +} diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 4aaf95de2a7..5c6a15b78eb 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -49,8 +49,14 @@ - + + + + + + + diff --git a/src/main/resources/view/TaskCard.fxml b/src/main/resources/view/TaskCard.fxml new file mode 100644 index 00000000000..e482482afe2 --- /dev/null +++ b/src/main/resources/view/TaskCard.fxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/TaskListPanel.fxml b/src/main/resources/view/TaskListPanel.fxml new file mode 100644 index 00000000000..a58887c89d1 --- /dev/null +++ b/src/main/resources/view/TaskListPanel.fxml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 1a70689bc0f..dc78981a481 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -151,6 +151,15 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void updateFilteredTaskList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredTaskList() { + throw new AssertionError("This method should not be called."); + } @Override public void addTask(Task task) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 9a4f7941cba..0ed98f6ed8c 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -124,6 +124,16 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void updateFilteredTaskList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredTaskList() { + throw new AssertionError("This method should not be called."); + } + @Override public void addTask(Task task) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index e1e913034c8..e3ad20f4c1c 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -158,6 +158,16 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void updateFilteredTaskList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredTaskList() { + throw new AssertionError("This method should not be called."); + } + @Override public void addTask(Task task) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 695a395388c..31b5adadc17 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -157,6 +157,16 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void updateFilteredTaskList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredTaskList() { + throw new AssertionError("This method should not be called."); + } + @Override public void addTask(Task task) { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index ba48ef0f9e1..a978311f7ac 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -117,6 +117,16 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void updateFilteredTaskList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredTaskList() { + throw new AssertionError("This method should not be called."); + } + @Override public void addTask(Task task) { throw new AssertionError("This method should not be called."); From daade7d97b0882f6f1fba69f5a00ee51f85f8bb9 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 30 Mar 2022 02:17:48 +0800 Subject: [PATCH 076/140] Add exception handler in UpdateCommandTest --- .../seedu/address/logic/commands/UpdateTaskCommandTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java index f138985f6c5..0d109f01e25 100644 --- a/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/UpdateTaskCommandTest.java @@ -9,6 +9,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.AddressBook; import seedu.address.model.Model; import seedu.address.model.ModelManager; @@ -19,7 +20,7 @@ public class UpdateTaskCommandTest { private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs(), getTypicalTaskList()); @Test - public void execute_allFieldsSpecifiedUnfilteredList_success() { + public void execute_allFieldsSpecifiedUnfilteredList_success() throws CommandException { Task updatedTask = new Task("test", "03/03/2022"); UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); descriptor.setDescription(updatedTask.getDescription()); @@ -63,7 +64,7 @@ public void createTaskWithoutDeadline_descriptorWithoutDeadline() { } @Test - public void execute_updateDuplicateTask_failure() { + public void execute_updateDuplicateTask_failure() throws CommandException { Task updatedTask = new Task("test", "03/03/2022"); UpdateTaskCommand.UpdateTaskDescriptor descriptor = new UpdateTaskCommand.UpdateTaskDescriptor(); descriptor.setDescription(updatedTask.getDescription()); From 7f3c77fae807884ebfcf97b18d2614b4d3635f24 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 30 Mar 2022 02:38:12 +0800 Subject: [PATCH 077/140] Remove white background for icon --- src/main/resources/images/NUScheduler_32.png | Bin 1887 -> 2187 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/images/NUScheduler_32.png b/src/main/resources/images/NUScheduler_32.png index 9fe78bff48a172e27e0726a8d4630fc9d34dc6f4..a8a2ee4f3687bdbc45150de22fc14fb0f071025f 100644 GIT binary patch delta 2071 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 nP6! Date: Wed, 30 Mar 2022 18:42:31 +0800 Subject: [PATCH 078/140] Remove unused methods --- .../address/model/task/UniqueTaskList.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/main/java/seedu/address/model/task/UniqueTaskList.java b/src/main/java/seedu/address/model/task/UniqueTaskList.java index 4be27564e30..b4c9c107d58 100644 --- a/src/main/java/seedu/address/model/task/UniqueTaskList.java +++ b/src/main/java/seedu/address/model/task/UniqueTaskList.java @@ -2,7 +2,6 @@ import static java.util.Objects.requireNonNull; -import java.util.Iterator; import java.util.List; import javafx.collections.FXCollections; @@ -19,7 +18,7 @@ * Supports a minimal set of list operations. * */ -public class UniqueTaskList implements Iterable { +public class UniqueTaskList { private final ObservableList internalList = FXCollections.observableArrayList(); private final ObservableList internalUnmodifiableList = @@ -85,21 +84,4 @@ public ObservableList asUnmodifiableObservableList() { return internalUnmodifiableList; } - @Override - public Iterator iterator() { - return internalList.iterator(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof UniqueTaskList // instanceof handles nulls - && internalList.equals(((UniqueTaskList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - } From 6aa27c912efbf49c9184e51b8fc764bb04aca540 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Wed, 30 Mar 2022 23:56:17 +0800 Subject: [PATCH 079/140] Update test classes --- src/main/java/seedu/address/model/Model.java | 6 -- .../seedu/address/model/ModelManager.java | 5 -- .../seedu/address/logic/LogicManagerTest.java | 6 ++ .../logic/commands/AddCommandTest.java | 5 -- .../logic/commands/AddTaskCommandTest.java | 5 -- .../logic/commands/DeleteTaskCommandTest.java | 5 -- .../logic/commands/FindTaskCommandTest.java | 5 -- .../logic/commands/ViewTaskCommandTest.java | 5 -- .../seedu/address/model/ModelManagerTest.java | 5 ++ .../model/task/UniqueTaskListTest.java | 64 +++++++++++++++++++ 10 files changed, 75 insertions(+), 36 deletions(-) create mode 100644 src/test/java/seedu/address/model/task/UniqueTaskListTest.java diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 86cc425406f..416f5a4eb55 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -87,12 +87,6 @@ public interface Model { */ void updateFilteredPersonList(Predicate predicate); - /** - * Updates the filter of the filtered person list to filter by the given {@code predicate}. - * @throws NullPointerException if {@code predicate} is null. - */ - void updateFilteredTaskList(Predicate predicate); - /** Returns an unmodifiable view of the filtered tasks list */ ObservableList getFilteredTaskList(); diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 5a4d3adf9a1..1699a9dcd5d 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -175,11 +175,6 @@ public ObservableList getFilteredTaskList() { return filteredTasks; } - @Override - public void updateFilteredTaskList(Predicate predicate) { - requireNonNull(predicate); - filteredTasks.setPredicate(predicate); - } //=========== TaskList ================================================================================== @Override diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index 13d18e77905..edb1f52ec3e 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -96,6 +96,12 @@ public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredPersonList().remove(0)); } + @Test + public void getFilteredTaskList_modifyList_throwsUnsupportedOperationException() { + assertThrows(UnsupportedOperationException.class, () -> logic.getFilteredTaskList().remove(0)); + } + + /** * Executes the command and confirms that * - no exceptions are thrown
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index dc78981a481..db736b085f9 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -151,11 +151,6 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } - @Override - public void updateFilteredTaskList(Predicate predicate) { - throw new AssertionError("This method should not be called."); - } - @Override public ObservableList getFilteredTaskList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java index 0ed98f6ed8c..c5ec080d96f 100644 --- a/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddTaskCommandTest.java @@ -124,11 +124,6 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } - @Override - public void updateFilteredTaskList(Predicate predicate) { - throw new AssertionError("This method should not be called."); - } - @Override public ObservableList getFilteredTaskList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java index e3ad20f4c1c..4e5c0300d66 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteTaskCommandTest.java @@ -158,11 +158,6 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } - @Override - public void updateFilteredTaskList(Predicate predicate) { - throw new AssertionError("This method should not be called."); - } - @Override public ObservableList getFilteredTaskList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java index 31b5adadc17..8718dc9992d 100644 --- a/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindTaskCommandTest.java @@ -157,11 +157,6 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } - @Override - public void updateFilteredTaskList(Predicate predicate) { - throw new AssertionError("This method should not be called."); - } - @Override public ObservableList getFilteredTaskList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java index a978311f7ac..4a069062cef 100644 --- a/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ViewTaskCommandTest.java @@ -117,11 +117,6 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } - @Override - public void updateFilteredTaskList(Predicate predicate) { - throw new AssertionError("This method should not be called."); - } - @Override public ObservableList getFilteredTaskList() { throw new AssertionError("This method should not be called."); diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 0965cd0ea5e..17803dfe657 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -105,6 +105,11 @@ public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0)); } + @Test + public void getFilteredTaskList_modifyList_throwsUnsupportedOperationException() { + assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredTaskList().remove(0)); + } + @Test public void equals() { AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build(); diff --git a/src/test/java/seedu/address/model/task/UniqueTaskListTest.java b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java new file mode 100644 index 00000000000..05c8c55504c --- /dev/null +++ b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java @@ -0,0 +1,64 @@ +package seedu.address.model.task; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.testutil.Assert.assertThrows; +import static seedu.address.testutil.TypicalTask.DUMMY_TASK; + +import org.junit.jupiter.api.Test; + +import seedu.address.logic.commands.exceptions.CommandException; + + +public class UniqueTaskListTest { + + private final UniqueTaskList uniqueTaskList = new UniqueTaskList(); + + @Test + public void contains_nullTask_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueTaskList.contains(null)); + } + + @Test + public void contains_taskNotInList_returnsFalse() { + assertFalse(uniqueTaskList.contains(DUMMY_TASK)); + } + + @Test + public void contains_taskInList_returnsTrue() throws CommandException { + uniqueTaskList.addTask(DUMMY_TASK, 1); + assertTrue(uniqueTaskList.contains(DUMMY_TASK)); + } + + @Test + public void add_nullTask_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueTaskList.addTask(null)); + } + + @Test + public void add_duplicateTask_throwsDuplicatePersonException() throws CommandException { + uniqueTaskList.addTask(DUMMY_TASK, 1); + assertThrows(CommandException.class, () -> uniqueTaskList.addTask(DUMMY_TASK, 1)); + } + + @Test + public void remove_nullTask_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> uniqueTaskList.deleteTask(null)); + } + + @Test + public void remove_existingTask_removesTask() { + UniqueTaskList expectedUniqueTaskList = uniqueTaskList; + Task test = new Task("test","30/03/2022"); + uniqueTaskList.addTask(test); + uniqueTaskList.deleteTask(1); + assertEquals(uniqueTaskList, expectedUniqueTaskList); + } + + @Test + public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() { + assertThrows(UnsupportedOperationException.class, () + -> uniqueTaskList.asUnmodifiableObservableList().remove(0)); + } +} From 09deea74837d9028d1b70d8e30fdb7d655dae2ea Mon Sep 17 00:00:00 2001 From: yumengtan Date: Thu, 31 Mar 2022 00:01:20 +0800 Subject: [PATCH 080/140] Update checkstyle --- .../java/seedu/address/model/task/UniqueTaskListTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/address/model/task/UniqueTaskListTest.java b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java index 05c8c55504c..c91d067d39a 100644 --- a/src/test/java/seedu/address/model/task/UniqueTaskListTest.java +++ b/src/test/java/seedu/address/model/task/UniqueTaskListTest.java @@ -50,7 +50,7 @@ public void remove_nullTask_throwsNullPointerException() { @Test public void remove_existingTask_removesTask() { UniqueTaskList expectedUniqueTaskList = uniqueTaskList; - Task test = new Task("test","30/03/2022"); + Task test = new Task("test", "30/03/2022"); uniqueTaskList.addTask(test); uniqueTaskList.deleteTask(1); assertEquals(uniqueTaskList, expectedUniqueTaskList); @@ -59,6 +59,6 @@ public void remove_existingTask_removesTask() { @Test public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() { assertThrows(UnsupportedOperationException.class, () - -> uniqueTaskList.asUnmodifiableObservableList().remove(0)); + -> uniqueTaskList.asUnmodifiableObservableList().remove(0)); } } From 517069efd233002f487d1eb167997585352a9ee2 Mon Sep 17 00:00:00 2001 From: yumengtan Date: Fri, 1 Apr 2022 02:01:42 +0800 Subject: [PATCH 081/140] Refactor: GUI --- .../address/commons/core/GuiSettings.java | 2 +- src/main/java/seedu/address/ui/UiManager.java | 2 +- src/main/resources/view/CommandBox.fxml | 5 +- src/main/resources/view/HelpWindow.css | 3 +- src/main/resources/view/MainWindow.fxml | 38 +++++---- src/main/resources/view/TaskCard.fxml | 1 - .../view/{DarkTheme.css => ThemePresets.css} | 80 ++++++++++++------- 7 files changed, 76 insertions(+), 55 deletions(-) rename src/main/resources/view/{DarkTheme.css => ThemePresets.css} (78%) diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/address/commons/core/GuiSettings.java index ba33653be67..861f3063729 100644 --- a/src/main/java/seedu/address/commons/core/GuiSettings.java +++ b/src/main/java/seedu/address/commons/core/GuiSettings.java @@ -11,7 +11,7 @@ public class GuiSettings implements Serializable { private static final double DEFAULT_HEIGHT = 600; - private static final double DEFAULT_WIDTH = 740; + private static final double DEFAULT_WIDTH = 800; private final double windowWidth; private final double windowHeight; diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index fd413ea84b1..8398e9d0c6d 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -65,7 +65,7 @@ void showAlertDialogAndWait(Alert.AlertType type, String title, String headerTex private static void showAlertDialogAndWait(Stage owner, AlertType type, String title, String headerText, String contentText) { final Alert alert = new Alert(type); - alert.getDialogPane().getStylesheets().add("view/DarkTheme.css"); + alert.getDialogPane().getStylesheets().add("view/ThemePresets.css"); alert.initOwner(owner); alert.setTitle(title); alert.setHeaderText(headerText); diff --git a/src/main/resources/view/CommandBox.fxml b/src/main/resources/view/CommandBox.fxml index 09f6d6fe9e4..f271f03465c 100644 --- a/src/main/resources/view/CommandBox.fxml +++ b/src/main/resources/view/CommandBox.fxml @@ -3,7 +3,6 @@ - - + + - diff --git a/src/main/resources/view/HelpWindow.css b/src/main/resources/view/HelpWindow.css index 17e8a8722cd..bb3ddda2977 100644 --- a/src/main/resources/view/HelpWindow.css +++ b/src/main/resources/view/HelpWindow.css @@ -1,5 +1,6 @@ #copyButton, #helpMessage { -fx-text-fill: white; + -fx-font-family: "Verdana"; } #copyButton { @@ -15,5 +16,5 @@ } #helpMessageContainer { - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#1d1d1d, -10%); } diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 5c6a15b78eb..af9f884c31d 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -6,24 +6,25 @@ + - + - + - - + +