From 7f8748029af6ab8c683eee5eabbb829faffb47e3 Mon Sep 17 00:00:00 2001 From: McNaBry Date: Wed, 1 Nov 2023 18:14:27 +0800 Subject: [PATCH 01/10] Update name validator --- src/main/java/seedu/address/model/contact/Name.java | 6 +++--- .../invalidPersonAddressBook.json | 2 +- .../java/seedu/address/logic/commands/CommandTestUtil.java | 2 +- .../java/seedu/address/logic/parser/ParserUtilTest.java | 2 +- src/test/java/seedu/address/model/contact/NameTest.java | 2 -- .../java/seedu/address/storage/JsonAdaptedContactTest.java | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/address/model/contact/Name.java b/src/main/java/seedu/address/model/contact/Name.java index d242d35f193..b856447e2ab 100644 --- a/src/main/java/seedu/address/model/contact/Name.java +++ b/src/main/java/seedu/address/model/contact/Name.java @@ -13,10 +13,10 @@ public class Name { "Names should only contain alphanumeric characters and spaces, and it should not be blank"; /** - * The first character of the name must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. + * Name must not be blank, must not contain any leading and trailing whitespaces + * and can have any number of characters. */ - public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + public static final String VALIDATION_REGEX = "[^\\s](.*[^\\s]|)"; public final String fullName; diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json index eef86fe2360..ec166914671 100644 --- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json @@ -1,6 +1,6 @@ { "persons": [ { - "name": "Person with invalid name field: Ha!ns Mu@ster", + "name": " ", "id" : "ca6e0af8-5092-47c0-baf7-18d6dc535823", "phone": "9482424", "email": "hans@example.com", diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 839d93f401b..7aca20ff4c1 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -62,7 +62,7 @@ public class CommandTestUtil { public static final String TAG_DESC_FRIEND = " " + FLAG_TAG + " " + VALID_TAG_FRIEND; public static final String TAG_DESC_HUSBAND = " " + FLAG_TAG + " " + VALID_TAG_HUSBAND; - public static final String INVALID_NAME_DESC = " " + FLAG_NAME + " " + "James&"; // '&' not allowed in names + public static final String INVALID_NAME_DESC = " " + FLAG_NAME + " "; // empty names not allowed public static final String INVALID_ID_DESC = " " + FLAG_ID + " " + "e91724&_18273"; // '&' not allowed in ids public static final String INVALID_PHONE_DESC = " " + FLAG_PHONE + " " + "911a"; // 'a' not allowed in phones public static final String INVALID_EMAIL_DESC = " " + FLAG_EMAIL + " " + "bob!yahoo"; // missing '@' symbol diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index bf2cc54ae10..c3dad8cd9e9 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -31,7 +31,7 @@ import seedu.address.model.tag.Tag; public class ParserUtilTest { - private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_NAME = " "; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_ADDRESS = " "; private static final String INVALID_EMAIL = "example.com"; diff --git a/src/test/java/seedu/address/model/contact/NameTest.java b/src/test/java/seedu/address/model/contact/NameTest.java index e05998724f9..0871bd28372 100644 --- a/src/test/java/seedu/address/model/contact/NameTest.java +++ b/src/test/java/seedu/address/model/contact/NameTest.java @@ -27,8 +27,6 @@ public void isValidName() { // invalid name assertFalse(Name.isValidName("")); // empty string assertFalse(Name.isValidName(" ")); // spaces only - assertFalse(Name.isValidName("^")); // only non-alphanumeric characters - assertFalse(Name.isValidName("peter*")); // contains non-alphanumeric characters // valid name assertTrue(Name.isValidName("peter jack")); // alphabets only diff --git a/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java b/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java index 56e0b8b6630..d2d246a8f06 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedContactTest.java @@ -27,7 +27,7 @@ public class JsonAdaptedContactTest { private static final String INVALID_TYPE = "asdf"; - private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_NAME = " "; private static final String INVALID_ID = "_12@-abc"; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_URL = " "; From 456b038c6a7193f0b73bfe1406d40b55e9d67015 Mon Sep 17 00:00:00 2001 From: tanshiyu Date: Thu, 2 Nov 2023 21:57:53 +0800 Subject: [PATCH 02/10] Add DG and UG --- docs/DeveloperGuide.md | 168 +++++++++++++++++++++++++++++++++++------ docs/UserGuide.md | 65 +++++++++++++--- 2 files changed, 199 insertions(+), 34 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 206366ab61b..dba469b8318 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -239,6 +239,81 @@ The following activity diagram summarizes what happens when a user executes a ne _{more aspects and alternatives to be added}_ +THIS IS MINE +### \[Proposed\] Adding Organization + +#### Proposed Implementation + +The proposed AddOrganization mechanism is facilitated by `AddOrganization`. It extends `AddContact`. + +These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. + +Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. + +Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. + +![UndoRedoState0](images/UndoRedoState0.png) + +Step 2. The user executes `delete 5` command to delete the 5th contact in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. + +![UndoRedoState1](images/UndoRedoState1.png) + +Step 3. The user executes `add n/David …​` to add a new contact. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. + +![UndoRedoState2](images/UndoRedoState2.png) + +
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. + +
+ +Step 4. The user now decides that adding the contact was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. + +![UndoRedoState3](images/UndoRedoState3.png) + +
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather +than attempting to perform the undo. + +
+ +The following sequence diagram shows how the undo operation works: + +![UndoSequenceDiagram](images/UndoSequenceDiagram.png) + +
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. + +
+ +The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. + +
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo. + +
+ +Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. + +![UndoRedoState4](images/UndoRedoState4.png) + +Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …​` command. This is the behavior that most modern desktop applications follow. + +![UndoRedoState5](images/UndoRedoState5.png) + +The following activity diagram summarizes what happens when a user executes a new command: + + + +#### Design considerations: + +**Aspect: How Add Organization executes:** + +* **Alternative 1 (current choice):** Adds the Organization with a JSON's key 'type': "Organization" + * Pros: Easy to implement. + * Cons: Might need to commit more lines of code + +* **Alternative 2:** Differentiate Organization with JSON key 'isOrganization': True + * Pros: Easy to implement + * Cons: If we are to add more data types, it we might need to add more isDataType fields + + ### \[Proposed\] Data archiving _{Explain here how the data archiving feature will be implemented}_ @@ -278,17 +353,21 @@ Allows for comprehensive tracking of job applications and the information of com Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| Priority | As a(n) ... | 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 contact | keep track of organizations and recruiters I'm interested in | -| `* * *` | user | delete contacts | remove organizations and recruiters that I no longer need | -| `* *` | user | edit my contacts via index and id | be up to date with changes in organization and recruiter details | -| `* *` | user | find contacts by saved details | locate a contact without going through the entire list | -| `* *` | user | filter organizations by job application status | get a summary of the statuses of what I've applied to | -| `* *` | user | tag contacts | organize my contact list for more efficient access of different categories | -| `* *` | efficient user | type shorter arguments and known values with auto-completion | type my command even more quickly | -| `*` | user | import and export contacts | share my list of contacts with my peers | +| Priority | As a(n) ... | I want to ... | So that I can ... | +|----------|----------------|--------------------------------------------------------------|----------------------------------------------------------------------------| +| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the app | +| `* * *` | user | find the relevant application data | see what I did for for my application to specific companies | +| `* * *` | user | adding a job application | keep track which organization I am applying to | +| `* * *` | user | add a new contact | keep track of organizations and recruiters I'm interested in | +| `* * *` | user | delete contacts | remove organizations and recruiters that I no longer need | +| `* *` | user | edit my contacts via index, id and name | be up to date with changes in organization and recruiter details | +| `* *` | user | find contacts by saved details | locate a contact without going through the entire list | +| `* *` | user | store recruiters and job application to organizations | I can see where the recruiter comes from and where I am applying to | +| `* *` | user | sort the application deadlines | be able to which application deadline ends first | +| `* *` | user | filter organizations by job application status | get a summary of the statuses of what I've applied to | +| `* *` | user | tag contacts | organize my contact list for more efficient access of different categories | +| `* *` | efficient user | type shorter arguments and known values with auto-completion | type my command even more quickly | +| `*` | user | import and export contacts | share my list of contacts with my peers | ### Use cases @@ -296,20 +375,36 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli +**Use case: Add an application** + +**MSS** + +1. User requests to add an application +2. Jobby adds the application into the specified organization +3. Jobby shows that the application has been added + + Use case ends. + +**Extensions** + +* 1a. The given application does not match to any Organization + * 1a1. Jobby shows an error message. + Use case ends. + + **Use case: Edit a contact** **MSS** 1. User requests to edit a contact 2. Jobby edits the contact - Use case ends. **Extensions** * 1a. The given request does not match with any contact. - * 1a1. Jobby shows an error message. - * + * 1a1. Jobby shows an error message. + Use case ends. @@ -328,25 +423,21 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli **Extensions** * 2a. The list is empty. - Use case ends. * 3a. The given index is invalid. - * 3a1. Jobby shows an error message. - + Use case resumes at step 2. * 3b. The given ID does not match to any organization. - * 3b1. Jobby shows an error message. - + Use case resumes at step 2. * 4a. The user has specified to delete recursively. - * 4a1. Jobby deletes all recruiter contacts associated with the recruiter (WIP) - + Use case ends. @@ -363,15 +454,44 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli **Extensions** * 1a. User requests to list organizations. - * 1a1. Jobby shows a list of organizations. - + Use case ends. * 1b. User requests to list recruiters. - * 1b1. Jobby shows a list of recruiters. + + Use case ends. + +**Use case: Find contacts** +**MSS** + +1. User requests to find contacts or applications +2. Jobby shows a list of contacts or applications found + + Use case ends. + +**Extensions** + +* 1a. User requests to find organizations. + * 1a1. Jobby shows a list of organizations that matches the search. + + Use case ends. + +* 1b. User requests to list recruiters. + * 1b1. Jobby shows a list of recruiters that matches the search. + + Use case ends. + +* 1c. User requests to list. + * 1c1. Jobby shows a list of application that matches the search. + + Use case ends. + +* 1d. No match found. + * 1d1. Jobby shows 0 matched result. + Use case ends. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 676aac2a9c1..b766506c617 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -239,6 +239,49 @@ Jobby data are saved automatically as a JSON file `[JAR file location]/data/jobb If your changes to the data file makes its format invalid, Jobby will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it. +### Applying to an organization: `Apply` + +Format: `add index/ id ` + + +App a contact to the address book of the given class type: Organization or Recruiter. + +Applying to a Organization by indicating it with the organization's index in the address book or the organization's unique id. + +This can be done by supplying the organization's `index` or `id` as the preamble. + +Details specifically will be explained the next sections. + + +#### Applying to an Organization: `add org index/org id` + +Format: `apply INDEX/ID --title TITLE [--desc DESCRIPTION] [--by DEADLINE: DD-MM-YYYY] [--stage APPLICATION STAGE: resume | online assessment | interview] [--stat STATUS: pending | offered | accepted | turned down]` + +Acceptable Parameters: +* `TITLE` can accept any value. + +* `DESCRIPTION` refers to the description of the internship application. + +* `DEADLINE` should be a valid date in the format DD-MM-YYYY. + +* `APPLICATION STAGE` should be 1 of 3 pre-determined stage: resume | online assessment | interview. + +* `STATUS` should be 1 of 4 pre-determined status: pending | offered | accepted | turned down. + + + +Examples: +* `add 1 --title SWE` + +* `add id_12345_1 --title Unit Tester --by 12-12-2023` + +* `add id_12345_1 --title Unit Tester --desc Unit testing for Google --by 12-12-2023 --stage resume` + +* `add id_12345_1 --title Junior Engineer --desc Junir role --by 12-12-2023 --stage resume --stat pending` + + + + -------------------------------------------------------------------------------------------------------------------- @@ -257,13 +300,15 @@ If your changes to the data file makes its format invalid, Jobby will discard al ## Command summary -Action | Format, Examples ---------|------------------ -**Add Organization** | `add --org --name [--id ID] [--phone NUMBER] [--email EMAIL] [--url URL] [--addr ADDRESS] [--stat STATUS] [--pos POSITION] [--tag TAG]...`
e.g., `add --org --name NUS --phone 0123456789 --email example@nus.edu.sg --url https://www.nus.edu.sg/ --stat pending --pos Research` -**Add Recruiter** | `add --rec --name [--id ID] [--oid ORG_ID] [--phone NUMBER] [--email EMAIL] [--url URL] [--addr ADDRESS] [--tag TAG]...`
e.g., `add --rec --name John Doe --oid paypal-sg` -**Clear** | `clear` -**Delete** | `delete INDEX [--recursive]` or
`delete --id ID [--recursive]`
e.g., `delete 3`, `delete --id 55tg` -**Edit** | Coming soon... -**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` -**List** | `list` -**Help** | `help` + Action | Format, Examples +----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + **Add Organization** | `add --org --name [--id ID] [--phone NUMBER] [--email EMAIL] [--url URL] [--addr ADDRESS] [--stat STATUS] [--pos POSITION] [--tag TAG]...`
e.g., `add --org --name NUS --phone 0123456789 --email example@nus.edu.sg --url https://www.nus.edu.sg/ --stat pending --pos Research` + **Add Recruiter** | `add --rec --name [--id ID] [--oid ORG_ID] [--phone NUMBER] [--email EMAIL] [--url URL] [--addr ADDRESS] [--tag TAG]...`
e.g., `add --rec --name John Doe --oid paypal-sg` + **Clear** | `clear` + **Delete** | `delete INDEX [--recursive]` or
`delete --id ID [--recursive]`
e.g., `delete 3`, `delete --id 55tg` + **Edit** | Coming soon... + **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` + **List** | `list` + **Help** | `help` + + From 4e0b3dc516a9eb1a4f2ab7bf86b450739533190e Mon Sep 17 00:00:00 2001 From: CJ-Lee01 Date: Thu, 2 Nov 2023 22:35:38 +0800 Subject: [PATCH 03/10] Update UG for update and delete applications --- docs/UserGuide.md | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b766506c617..4af7ede57d7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -253,7 +253,7 @@ This can be done by supplying the organization's `index` or `id` as the preamble Details specifically will be explained the next sections. -#### Applying to an Organization: `add org index/org id` +#### Applying to an Organization: `apply` Format: `apply INDEX/ID --title TITLE [--desc DESCRIPTION] [--by DEADLINE: DD-MM-YYYY] [--stage APPLICATION STAGE: resume | online assessment | interview] [--stat STATUS: pending | offered | accepted | turned down]` @@ -271,15 +271,39 @@ Acceptable Parameters: Examples: -* `add 1 --title SWE` +* `apply 1 --title SWE` -* `add id_12345_1 --title Unit Tester --by 12-12-2023` +* `apply id_12345_1 --title Unit Tester --by 12-12-2023` -* `add id_12345_1 --title Unit Tester --desc Unit testing for Google --by 12-12-2023 --stage resume` +* `apply id_12345_1 --title Unit Tester --desc Unit testing for Google --by 12-12-2023 --stage resume` -* `add id_12345_1 --title Junior Engineer --desc Junir role --by 12-12-2023 --stage resume --stat pending` +* `apply id_12345_1 --title Junior Engineer --desc Junir role --by 12-12-2023 --stage resume --stat pending` +### Deleting a job application +Deletes the specified job application from the list. +Format: `delete --application INDEX` + +* `INDEX` refers to the index number shown on the list and must be a positive integer. + +Examples: +* `delete --application 1` deletes the first job application in the list. + + +### Updating/Editing a job application +Updates the job applications with the input fields. + +Format: `edit --application INDEX [--title TITLE] [--desc DESCRIPTION] [--by DEADLINE] [--stat STATUS] [--stage STAGE]` + +* `INDEX` refers to the index number shown on the list and must be a positive integer. +* At least one of the optional fields must be specified. +* `STATUS` is one of `pending`, `offered`, `accepted`, `turned down` +* `STAGE` is one of `resume`, `online assessment`, `interview` + +Examples: +* `edit --application 1 --title SWE --desc Pay: $100 per hour` +* `edit --application 1 --stat rejected` +* `edit --application 1 --stage interview` @@ -306,9 +330,10 @@ Examples: **Add Recruiter** | `add --rec --name [--id ID] [--oid ORG_ID] [--phone NUMBER] [--email EMAIL] [--url URL] [--addr ADDRESS] [--tag TAG]...`
e.g., `add --rec --name John Doe --oid paypal-sg` **Clear** | `clear` **Delete** | `delete INDEX [--recursive]` or
`delete --id ID [--recursive]`
e.g., `delete 3`, `delete --id 55tg` - **Edit** | Coming soon... - **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` - **List** | `list` + **Edit** | `edit INDEX ...` or
`edit ID ...` or
`edit --application INDEX ...` + **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` + **Apply** | `apply INDEX [--title TITLE] [--desc DESCRIPTION] [--by DEADLINE] [--stage STAGE] [--stat STATUS]` or
`apply ID [--title TITLE] [--desc DESCRIPTION] [--by DEADLINE] [--stage STAGE] [--stat STATUS]` + **List** | `list [--FLAG_TO_SORT]` **Help** | `help` From 844a683239722643b6ecf454ae16cfc6eaa8e0aa Mon Sep 17 00:00:00 2001 From: CJ-Lee01 Date: Thu, 2 Nov 2023 22:47:37 +0800 Subject: [PATCH 04/10] Add sort to UG --- docs/UserGuide.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4af7ede57d7..26466218071 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -305,6 +305,22 @@ Examples: * `edit --application 1 --stat rejected` * `edit --application 1 --stage interview` +### Sort `sort` +Sorts contacts or applications by the specified flag. + +Format: `sort --FLAG_TO_SORT` + +* Currently only the following sorting functions are supported: + * For contacts: + * `--addr` + * `--email` + * `--name` + * `--id` + * `--phone` + * `--url` + * For job applications + * `--stale`: Sorts by last updated applications + -------------------------------------------------------------------------------------------------------------------- @@ -333,7 +349,8 @@ Examples: **Edit** | `edit INDEX ...` or
`edit ID ...` or
`edit --application INDEX ...` **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` **Apply** | `apply INDEX [--title TITLE] [--desc DESCRIPTION] [--by DEADLINE] [--stage STAGE] [--stat STATUS]` or
`apply ID [--title TITLE] [--desc DESCRIPTION] [--by DEADLINE] [--stage STAGE] [--stat STATUS]` - **List** | `list [--FLAG_TO_SORT]` + **List** | `list [--FLAG_TO_FILTER]` + **Sort** | `sort [--FLAG_TO_SORT]` **Help** | `help` From bc44016c3948485e9fe800ca220b005c04e0a6ab Mon Sep 17 00:00:00 2001 From: McNaBry Date: Thu, 2 Nov 2023 23:19:15 +0800 Subject: [PATCH 05/10] Update email validator --- .../seedu/address/model/contact/Email.java | 18 +++++++--------- .../address/model/contact/EmailTest.java | 21 ++++++++----------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/main/java/seedu/address/model/contact/Email.java b/src/main/java/seedu/address/model/contact/Email.java index fd5a1a41735..afb061ba5a6 100644 --- a/src/main/java/seedu/address/model/contact/Email.java +++ b/src/main/java/seedu/address/model/contact/Email.java @@ -12,21 +12,17 @@ public class Email { private static final String SPECIAL_CHARACTERS = "+_.-"; public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " + "and adhere to the following constraints:\n" - + "1. The local-part should only contain alphanumeric characters and these special characters, excluding " - + "the parentheses, (" + SPECIAL_CHARACTERS + "). The local-part may not start or end with any special " - + "characters.\n" + + "1. The local-part can contain any character except whitespace or @\n" + "2. This is followed by a '@' and then a domain name. The domain name is made up of domain labels " + "separated by periods.\n" + "The domain name must:\n" + " - end with a domain label at least 2 characters long\n" - + " - have each domain label start and end with alphanumeric characters\n" - + " - have each domain label consist of alphanumeric characters, separated only by hyphens, if any."; - // alphanumeric and special characters - private static final String ALPHANUMERIC_NO_UNDERSCORE = "[^\\W_]+"; // alphanumeric characters except underscore - private static final String LOCAL_PART_REGEX = "^" + ALPHANUMERIC_NO_UNDERSCORE + "([" + SPECIAL_CHARACTERS + "]" - + ALPHANUMERIC_NO_UNDERSCORE + ")*"; - private static final String DOMAIN_PART_REGEX = ALPHANUMERIC_NO_UNDERSCORE - + "(-" + ALPHANUMERIC_NO_UNDERSCORE + ")*"; + + " - not contain any whitespace\n"; + + private static final String ALL_ACCEPTED_CHARS_NO_WHITESPACE = "[^\\s@]"; + private static final String LOCAL_PART_REGEX = "^" + ALL_ACCEPTED_CHARS_NO_WHITESPACE + "+"; + private static final String DOMAIN_PART_REGEX = ALL_ACCEPTED_CHARS_NO_WHITESPACE + + "(-" + ALL_ACCEPTED_CHARS_NO_WHITESPACE + ")*"; private static final String DOMAIN_LAST_PART_REGEX = "(" + DOMAIN_PART_REGEX + "){2,}$"; // At least two chars private static final String DOMAIN_REGEX = "(" + DOMAIN_PART_REGEX + "\\.)*" + DOMAIN_LAST_PART_REGEX; public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@" + DOMAIN_REGEX; diff --git a/src/test/java/seedu/address/model/contact/EmailTest.java b/src/test/java/seedu/address/model/contact/EmailTest.java index 2c2749f24a7..8d2df02daf2 100644 --- a/src/test/java/seedu/address/model/contact/EmailTest.java +++ b/src/test/java/seedu/address/model/contact/EmailTest.java @@ -35,31 +35,28 @@ public void isValidEmail() { // invalid parts assertFalse(Email.isValidEmail("peterjack@-")); // invalid domain name - assertFalse(Email.isValidEmail("peterjack@exam_ple.com")); // underscore in domain name assertFalse(Email.isValidEmail("peter jack@example.com")); // spaces in local part assertFalse(Email.isValidEmail("peterjack@exam ple.com")); // spaces in domain name assertFalse(Email.isValidEmail(" peterjack@example.com")); // leading space assertFalse(Email.isValidEmail("peterjack@example.com ")); // trailing space assertFalse(Email.isValidEmail("peterjack@@example.com")); // double '@' symbol assertFalse(Email.isValidEmail("peter@jack@example.com")); // '@' symbol in local part - assertFalse(Email.isValidEmail("-peterjack@example.com")); // local part starts with a hyphen - assertFalse(Email.isValidEmail("peterjack-@example.com")); // local part ends with a hyphen - assertFalse(Email.isValidEmail("peter..jack@example.com")); // local part has two consecutive periods assertFalse(Email.isValidEmail("peterjack@example@com")); // '@' symbol in domain name - assertFalse(Email.isValidEmail("peterjack@.example.com")); // domain name starts with a period - assertFalse(Email.isValidEmail("peterjack@example.com.")); // domain name ends with a period - assertFalse(Email.isValidEmail("peterjack@-example.com")); // domain name starts with a hyphen - assertFalse(Email.isValidEmail("peterjack@example.com-")); // domain name ends with a hyphen - assertFalse(Email.isValidEmail("peterjack@example.c")); // top level domain has less than two chars + assertTrue(Email.isValidEmail("a@bc")); // minimal + assertTrue(Email.isValidEmail("test@localhost")); // alphabets only + assertTrue(Email.isValidEmail("123@145")); // numeric local part and domain name // valid email + assertTrue(Email.isValidEmail("peterjack@exam_ple.com")); // underscore in domain name + assertTrue(Email.isValidEmail("-peterjack@example.com")); // local part starts with a hyphen + assertTrue(Email.isValidEmail("peterjack-@example.com")); // local part ends with a hyphen + assertTrue(Email.isValidEmail("peter..jack@example.com")); // local part has two consecutive periods + assertTrue(Email.isValidEmail("peterjack@-example.com")); // domain name starts with a hyphen + assertTrue(Email.isValidEmail("peterjack@example.com-")); // domain name ends with a hyphen assertTrue(Email.isValidEmail("PeterJack_1190@example.com")); // underscore in local part assertTrue(Email.isValidEmail("PeterJack.1190@example.com")); // period in local part assertTrue(Email.isValidEmail("PeterJack+1190@example.com")); // '+' symbol in local part assertTrue(Email.isValidEmail("PeterJack-1190@example.com")); // hyphen in local part - assertTrue(Email.isValidEmail("a@bc")); // minimal - assertTrue(Email.isValidEmail("test@localhost")); // alphabets only - assertTrue(Email.isValidEmail("123@145")); // numeric local part and domain name assertTrue(Email.isValidEmail("a1+be.d@example1.com")); // mixture of alphanumeric and special characters assertTrue(Email.isValidEmail("peter_jack@very-very-very-long-example.com")); // long domain name assertTrue(Email.isValidEmail("if.you.dream.it_you.can.do.it@example.com")); // long local part From 98566af364925328ae701ab08b54de85b9eaf241 Mon Sep 17 00:00:00 2001 From: Wern Date: Thu, 2 Nov 2023 23:31:22 +0800 Subject: [PATCH 06/10] Fix test --- .../invalidPersonAddressBook.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json index 9ecd3d12b32..55b5be3b01d 100644 --- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json @@ -3,7 +3,7 @@ "name": "Hans Muster", "id": "a8dfa74c-2229-4f4f-99a5-336c25e6783e", "phone": "9482424", - "email": "invalid@email!3e", + "email": "invalid@email!@3e", "address": "4th street" } ] } From a4faaa255b691d06ac2a2fee29b59ce14ef672dd Mon Sep 17 00:00:00 2001 From: Wern Date: Thu, 2 Nov 2023 23:41:50 +0800 Subject: [PATCH 07/10] Update variable name and constraint message --- .../seedu/address/model/contact/Email.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/address/model/contact/Email.java b/src/main/java/seedu/address/model/contact/Email.java index afb061ba5a6..fe1f47ead16 100644 --- a/src/main/java/seedu/address/model/contact/Email.java +++ b/src/main/java/seedu/address/model/contact/Email.java @@ -9,20 +9,18 @@ */ public class Email { - private static final String SPECIAL_CHARACTERS = "+_.-"; + public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " - + "and adhere to the following constraints:\n" - + "1. The local-part can contain any character except whitespace or @\n" - + "2. This is followed by a '@' and then a domain name. The domain name is made up of domain labels " - + "separated by periods.\n" - + "The domain name must:\n" - + " - end with a domain label at least 2 characters long\n" - + " - not contain any whitespace\n"; + + "and adhere to the following constraints:\n\n" + + "1. There must be exactly one '@' sign separating the local part and domain name.\n" + + "2. Both parts may not contain whitespace.\n" + + "3. The domain name is made up of domain labels separated by periods, " + + " and must end with a domain label at least 2 characters long.\n"; - private static final String ALL_ACCEPTED_CHARS_NO_WHITESPACE = "[^\\s@]"; - private static final String LOCAL_PART_REGEX = "^" + ALL_ACCEPTED_CHARS_NO_WHITESPACE + "+"; - private static final String DOMAIN_PART_REGEX = ALL_ACCEPTED_CHARS_NO_WHITESPACE - + "(-" + ALL_ACCEPTED_CHARS_NO_WHITESPACE + ")*"; + private static final String ALL_ACCEPTED_CHARS = "[^\\s@]"; // Very loose match to support International Emails + private static final String LOCAL_PART_REGEX = "^" + ALL_ACCEPTED_CHARS + "+"; + private static final String DOMAIN_PART_REGEX = ALL_ACCEPTED_CHARS + + "(-" + ALL_ACCEPTED_CHARS + ")*"; private static final String DOMAIN_LAST_PART_REGEX = "(" + DOMAIN_PART_REGEX + "){2,}$"; // At least two chars private static final String DOMAIN_REGEX = "(" + DOMAIN_PART_REGEX + "\\.)*" + DOMAIN_LAST_PART_REGEX; public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@" + DOMAIN_REGEX; From 7820133958b299a3d36c1756513ec600c2646ddc Mon Sep 17 00:00:00 2001 From: Wern Date: Fri, 3 Nov 2023 00:05:43 +0800 Subject: [PATCH 08/10] Update job title validator and tests --- .../java/seedu/address/model/jobapplication/Deadline.java | 3 +-- .../java/seedu/address/model/jobapplication/JobTitle.java | 6 +++--- .../java/seedu/address/logic/parser/ParserUtilTest.java | 2 +- .../seedu/address/storage/JsonAdaptedApplicationTest.java | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/address/model/jobapplication/Deadline.java b/src/main/java/seedu/address/model/jobapplication/Deadline.java index e1a8a72fc9f..d4069c04e9d 100644 --- a/src/main/java/seedu/address/model/jobapplication/Deadline.java +++ b/src/main/java/seedu/address/model/jobapplication/Deadline.java @@ -16,8 +16,7 @@ public class Deadline implements Comparable { public static final String MESSAGE_CONSTRAINTS = "Deadlines should be in the format of DD-MM-YYYY"; - //TODO: To verify that this regex is actually correct - public static final String VALIDATION_REGEX = "^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[012])-(19|20)\\d\\d$"; + public static final String VALIDATION_REGEX = "^(0?[1-9]|[12][0-9]|3[01])-(0?[1-9]|1[012])-\\d{4}$"; private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("d-M-y"); public final LocalDate deadline; diff --git a/src/main/java/seedu/address/model/jobapplication/JobTitle.java b/src/main/java/seedu/address/model/jobapplication/JobTitle.java index c094dbfedb7..a32e7e24fa5 100644 --- a/src/main/java/seedu/address/model/jobapplication/JobTitle.java +++ b/src/main/java/seedu/address/model/jobapplication/JobTitle.java @@ -11,10 +11,10 @@ public class JobTitle { "Job title should only contain alphanumeric characters, underscores and dashes, and it should not be blank"; /** - * The first character of the id must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. + * Job titles must not be blank, must not contain any leading and trailing whitespaces + * and can have any number of characters. */ - public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + public static final String VALIDATION_REGEX = "[^\\s](.*[^\\s]|)"; public final String title; diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index c3dad8cd9e9..d062aad4b4e 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -37,7 +37,7 @@ public class ParserUtilTest { private static final String INVALID_EMAIL = "example.com"; private static final String INVALID_TAG = "#friend"; private static final String INVALID_DEADLINE = "11-20-2022"; - private static final String INVALID_JOB_TITLE = "$1111"; + private static final String INVALID_JOB_TITLE = " "; private static final String INVALID_JOB_STATUS = "pen"; private static final String INVALID_APPLICATION_STAGE = "res"; diff --git a/src/test/java/seedu/address/storage/JsonAdaptedApplicationTest.java b/src/test/java/seedu/address/storage/JsonAdaptedApplicationTest.java index b33fff6a765..f8ca7e78972 100644 --- a/src/test/java/seedu/address/storage/JsonAdaptedApplicationTest.java +++ b/src/test/java/seedu/address/storage/JsonAdaptedApplicationTest.java @@ -20,8 +20,8 @@ class JsonAdaptedApplicationTest { private static final String INVALID_OID = " "; - private static final String INVALID_ORG_NAME = "@@@@"; - private static final String INVALID_TITLE = "@D"; + private static final String INVALID_ORG_NAME = " extra whitespace? "; + private static final String INVALID_TITLE = " "; private static final String INVALID_DESCRIPTION = " "; private static final String INVALID_DEADLINE = "22-22-2222"; private static final String INVALID_STATUS = "PEN"; From f8b9435aa3237a9f3a6c1568ae6c505281cbe8f9 Mon Sep 17 00:00:00 2001 From: Wern Date: Fri, 3 Nov 2023 00:09:48 +0800 Subject: [PATCH 09/10] Update apply command usage --- .../seedu/address/logic/commands/ApplyCommand.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/ApplyCommand.java b/src/main/java/seedu/address/logic/commands/ApplyCommand.java index dfd490ec3ee..7292c06304d 100644 --- a/src/main/java/seedu/address/logic/commands/ApplyCommand.java +++ b/src/main/java/seedu/address/logic/commands/ApplyCommand.java @@ -74,11 +74,11 @@ public class ApplyCommand extends Command { public static final String MESSAGE_USAGE = "Adds a new job application.\n" + "Parameters: " + "INDEX/ID " - + FLAG_TITLE + " TITLE " // Title - + FLAG_DESCRIPTION + " DESCRIPTION " // Description - + FLAG_DEADLINE + " DEADLINE: DD-MM-YYYY " // Deadline - + FLAG_STAGE + " APPLICATION STAGE: resume | online assessment | interview " // Application stage - + FLAG_STATUS + " STATUS: pending | offered | accepted | turned down "; // Status + + FLAG_TITLE + " TITLE " + + "[" + FLAG_DESCRIPTION + " DESCRIPTION] " + + "[" + FLAG_DEADLINE + " DEADLINE: DD-MM-YYYY] " + + "[" + FLAG_STAGE + " APPLICATION STAGE: resume/online assessment/interview] " + + "[" + FLAG_STATUS + " STATUS: pending/offered/accepted/turned down] "; public static final String MESSAGE_APPLY_SUCCESS = "Added application: %1$s to %2$s"; public static final String MESSAGE_ATTEMPT_TO_ADD_TO_NON_ORG = "Attempted to apply to a non-organization: %1$s"; From f1ced57a260d2c04c08322116f433969b8f74de4 Mon Sep 17 00:00:00 2001 From: Wern Date: Fri, 3 Nov 2023 00:15:22 +0800 Subject: [PATCH 10/10] Fix Id message constraint --- src/main/java/seedu/address/model/contact/Id.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/address/model/contact/Id.java b/src/main/java/seedu/address/model/contact/Id.java index abbd1959902..162373d5050 100644 --- a/src/main/java/seedu/address/model/contact/Id.java +++ b/src/main/java/seedu/address/model/contact/Id.java @@ -12,7 +12,8 @@ */ public class Id { public static final String MESSAGE_CONSTRAINTS = - "Id should only contain alphanumeric characters, underscores and dashes, and it should not be blank"; + "Id should only contain alphanumeric characters, underscores and dashes, and it should not be blank. " + + "Ids must also start with alphabets, and may not have consecutive underscores and/or dashes."; /** * The first character of the id must not be a whitespace,