diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ea352d0597b..9044c39cc3d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -24,6 +24,7 @@ Refer to the guide [_Setting up and getting started_](SettingUp.md).
:bulb: **Tip:** The `.puml` files used to create diagrams in this document `docs/diagrams` folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams. +
### Architecture @@ -72,6 +73,8 @@ The **API** of this component is specified in [`Ui.java`](https://github.com/AY2 ![Structure of the UI Component](images/UiClassDiagram.png) +The UI interface is implemented by `UiManager`. + The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI. The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2324S2-CS2103-F08-3/tp/blob/master/src/main/java/staffconnect/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2324S2-CS2103-F08-3/tp/blob/master/src/main/resources/view/MainWindow.fxml) @@ -79,9 +82,9 @@ The `UI` component uses the JavaFx UI framework. The layout of these UI parts ar The `UI` component, * executes user commands using the `Logic` component. -* listens for changes to `Model` data so that the UI can be updated with the modified data. -* keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands. -* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`. +* listens for changes to data in `Model` component so that the UI can be updated with the modified data. +* keeps a reference to the `Logic` component, because the `UIManager` relies on the `Logic` component to execute commands. +* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model` component. ### Logic component @@ -100,11 +103,11 @@ The sequence diagram below illustrates the interactions within the `Logic` compo How the `Logic` component works: -1. When `Logic` is called upon to execute a command, it is passed to an `StaffConnectParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command. -1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`. -1. The command can communicate with the `Model` when it is executed (e.g. to delete a person).
+1. When `LogicManager` is called upon to execute a command, it is passed to an `StaffConnectParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command. +2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`. +3. The command can communicate with the `Model` component when it is executed (e.g. to delete a person).
Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the `Model`) to achieve. -1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. +4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `LogicManger`. Here are the other classes in `Logic` (omitted from the class diagram above) that are used for parsing a user command: @@ -115,25 +118,24 @@ How the parsing works: * All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. ### Model component + **API** : [`Model.java`](https://github.com/AY2324S2-CS2103-F08-3/tp/blob/master/src/main/java/staffconnect/model/Model.java) - The `Model` component, * stores the staff book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). * stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. * stores a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects. -* does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components) - +* does not depend on any of the other three components (as the `Model` component represents data entities of the domain, they should make sense on their own without depending on other components) +* stores the meeting book data i.e., all `Meeting` objects (which are contained in a `UniqueMeetingList` object) in each `Person` object.
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `StaffBook`, which `Person` references. This allows `StaffBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
- ### Storage component **API** : [`Storage.java`](https://github.com/AY2324S2-CS2103-F08-3/tp/blob/master/src/main/java/staffconnect/storage/Storage.java) @@ -166,11 +168,11 @@ The sequence diagram below shows how the edit command `edit 1 p/ 12345678` goes
:information_source: **Note:** The lifeline for `EditCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
-1. When the user issues the command `edit 1 p/ 12345678`, `Logic` is called upon to execute the command, it is passed to the `StaffConnectParser` object which creates a `EditCommandParser` to parse the arguments for the edit command. -2. The parsing of `EditCommandParser` results in a new `EditCommand` initialized by an index `int` and a `EditPersonDescriptor`. The datails will be explained later. +1. When the user issues the command `edit 1 p/ 12345678`, `LogicManager` is called upon to execute the command, it is passed to the `StaffConnectParser` object which creates a `EditCommandParser` to parse the arguments for the edit command. +2. The parsing of `EditCommandParser` results in a new `EditCommand` initialized by an integer `index` and a `EditPersonDescriptor`. The datails will be explained later. 3. When the `EditCommand` is executed, it creates a new `Person` object according to the `EditPersonDescriptor` passed to it, and replaces the old `Person` object with the new one. -4. The command communicates with the `Model` when it is executed. More specifically, it calls the `updateFilteredPersonList()` method using a `Predicate` object which simply evaluates to true for all `Person`. The intension is that no `Person` will be filtered out in an edit command. -5. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`, to show in the `UI` component the success message that the `Person` at the given index is updated with the new information. +4. The command communicates with the `Model` component when it is executed. More specifically, it calls the `updateFilteredPersonList()` method using a `Predicate` object which simply evaluates to true for all `Person`. The intension is that no `Person` will be filtered out in an edit command. +5. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `LogicManager`, to show in the `UI` component the success message that the `Person` at the given index is updated with the new information. The below sequence diagram goes into more detail on how the command is parsed in `EditCommandParser`. @@ -182,18 +184,18 @@ The below sequence diagram goes into more detail on how the command is parsed in The below activity diagram illustrates the process when a user executes a edit command. - + #### Why edit is implemented this way -The command calls `SetPerson()` method in `Model` and then refresh the list of `Person` objects. +The command calls `SetPerson()` method in `Model` component and then refresh the list of `Person` objects. Below are some explanations for some implementation details. Check if `editPersonDescriptor.isAnyFieldEdited()`: -This is to make sure at least one field is modified, or the command will not have any impact on the `Model`. +This is to make sure at least one field is modified, or the command will not have any impact on the `Model` component. Call `model.updateFilteredPersonList())` with a `Predicate` that always evaluates to true: -This is to refresh the list of `Person` in `Model`. +This is to refresh the list of `Person` in `Model` component. ### Find feature @@ -208,8 +210,8 @@ The sequence diagram below explains how the find command `find Alex` goes throug 1. When user types in `find Alex`, it is passed to `StaffConnectParser`. 2. `StaffconnectParser` then creates a `FindCommandParser` that will parse `Alex` to create a `FindCommand` which utilizes a predicate judge whether `Alex` is contained in the person's name. -3. In `FindCommand`, `Model` executes `updateFilteredPersonList()` method using the predicate mentioned above. -4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`, to show in the `UI` component the number of persons listed with `Alex` in the name. +3. In `FindCommand`, `ModelManager` executes `updateFilteredPersonList()` method using the predicate mentioned above. +4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `LogicManager`, to show in the `UI` component the number of persons listed with `Alex` in the name. The below sequence diagram goes into more detail on how the command is parsed in `EditCommandParser`. @@ -220,7 +222,7 @@ The below sequence diagram goes into more detail on how the command is parsed in The below activity diagram illustrates the process when a user executes a find command. - + #### Why find is implemented this way @@ -241,10 +243,10 @@ The sequence diagram below shows how the filter command `filter f/Computing` goe
:information_source: **Note:** The lifeline for `FilterCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
-1. When the user issues the command `filter f/Computing`, `Logic` is called upon to execute the command, it is passed to the `StaffConnectParser` object which creates a `FilterCommandParser` to parse the arguments for the filter command. +1. When the user issues the command `filter f/Computing`, `LogicManager` is called upon to execute the command, it is passed to the `StaffConnectParser` object which creates a `FilterCommandParser` to parse the arguments for the filter command. 2. This results in a `FilterCommand` object, which then creates a `Predicate` object. -3. The command communicates with the `Model` when it is executed. More specifically, it calls the `updateFilteredPersonList()` method using the `Predicate` object created earlier as the argument. Note that although it is shown as a single step in the diagram (for simplicity), in the code it takes several. -4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`, to show in the `UI` component the number of persons listed with the `Faculty` value of "Computing". +3. The command communicates with the `Model` component when it is executed. More specifically, it calls the `updateFilteredPersonList()` method using the `Predicate` object created earlier as the argument. Note that although it is shown as a single step in the diagram (for simplicity), in the code it takes several. +4. The result of the command execution is encapsulated as a `CommandResult` object which is returned from `LogicManager`, to show in the `UI` component the number of persons listed with the `Faculty` value of "Computing". The below sequence diagram goes into more detail on how the command is parsed in `FilterCommandParser`. @@ -294,10 +296,9 @@ The sequence diagram for executing a **"sort n/"** is shown below: - The following activity diagram summarizes what happens when a user executes a new sort command: - + #### Why sort is implemented this way @@ -305,7 +306,7 @@ The main operation for the sort feature is the `updateSortedPersonList(Comparato The following are some explanations for decisions made in the implementation of the sort feature. Need for multiple `Comparator` objects: -This is to keep in view for when other commands or enhancements may need the separate attribute predicates. +This is to keep in view for when other commands or enhancements may need the separate attribute predicates. Need for `MultiComparator` object: This is to map the 1 or more comparator objects and act as a layer of abstraction where `SortCommmand` does need to know how many attributes are used in sorting. @@ -314,6 +315,7 @@ This is to map the 1 or more comparator objects and act as a layer of abstractio This is to prevent `SortCommand` from taking on more responsibilities (Separation of Concerns). #### What designs were considered: + **Aspect: Determining order of sorting of attribute(s):** * **Current Design:** Get sorting order of attribute(s) from user input. @@ -334,7 +336,8 @@ This is to prevent `SortCommand` from taking on more responsibilities (Separatio * Pros: Easy to implement, controlled and less likely to be used incorrectly. This increase ease of use for users. * Cons: Limited sorting and lesser functionality. -### Meeting feature + +### Meeting Feature Meeting is feature that allows the user to keep track of any events they may have with the particular contact. It contains the description of the meeting event with the date and time it would occur. @@ -343,10 +346,33 @@ Meeting is feature that allows the user to keep track of any events they may hav Meeting contains two attributes ```MeetingDescription``` and ```MeetingDateTime``` class. ```MeetingDescription``` is used to handle any valid description of the meeting with only alphanumeric values, while the ```MeetingDateTime``` is used to handle any valid date time values. Each of this meeting are stored in a list data class ```MeetingList``` that -contains each of the meetings related to each other stored in an ```ObservableList```. The ``` MeetingManager ``` is +contains each of the meetings related to each other stored in an ```ObservableList```. The ```MeetingManager``` is used to manage any operations that require viewing or sorting of meetings from the ```MeetingList``` class. -#### What designs were considered: +The operations for adding and deleting meeting are handled by `AddMeetingCommand` and `DeleteMeetingCommand`, which are supported by `AddMeetingCommandParser` and `DeleteMeetingCommandParser` respectively. + +1. The user enters `meeting-add 2 d/Finals s/20/04/2024 15:00` to add a meeting or `meeting-delete 1 i/1` to delete a meeting. +2. `Logic Manager` receives the user input which is parsed by `StaffConnectParser`. +3. After splitting the user input into `commandWord` and `arguments` based on the regex pattern of the user input, the `StaffConnectParser` invokes the `AddMeetingCommandParser`or`DeleteMeetingCommandParser` based on the `commandWord`. Calling the method `parse` with `arguments` as the method arguments, and getting supported by parsing methods from `ParsedUtil`. +4. `AddMeetingCommand` or `DeleteMeetingCommand` is created with the parsed values. +5. `Logic Manager` executes the `AddMeetingCommand` or `DeleteMeetingCommand`, which handles adding/removing meeting from the `Person` respectively and updates the model with the new information. + +Below is the sequence diagram for parsing inputs with `AddMeetingCommandParser` executing `meeting-add 2 d/Finals s/20/04/2024 15:00`: +
![AddMeetingCommandParser Sequence Diagram](images/AddMeetingParserSequenceDiagram.png) +
Below in the in-depth reference of how `AddMeetingCommandParser` utilise `ParseUtil` to parse the arguments: +
![Add Parser Reference Diagram](images/AddParserRefrenceDiagram.png) +
Similarly, the sequence diagram for parsing inputs with `DeleteMeetingCommandParser` executing `meeting-delete 1 i/1`: +
![DeleteMeetingCommandParser Sequence Diagram](images/DeleteMeetingParserSequenceDiagram.png) +

+After parsing, the commands are executed by the logic manager as show below. (Execute in the diagrams below comes form the logic manager) +
Below is the sequence diagram for adding meeting with `AddMeetingCommand`: +
![AddMeetingCommand Sequence Diagram](images/AddMeetingSequenceDiagram.png) +
Similarly the sequence diagram for deleting meeting with `DeleteMeetingCommand`: +
![DeleteMeetingCommand Sequence Diagram](images/DeleteMeetingSequenceDiagram.png) +
Below is the sequence diagram of how both `AddMeetingCommand` and `DeleteMeetingCommand` copies the selected person from the model for editing: +
![Copy selectedPerson](images/MeetingCopyPerson.png) + +#### What are the design considered: **Aspect: How the meetings are stored :** @@ -360,27 +386,75 @@ used to manage any operations that require viewing or sorting of meetings from t ### Fav/unfav feature -The feature enables us to sets/remove a particular contact using an index as favourite. +This feature enables us to sets/remove a particular contact using an index as favourite. + +
+ +:information_source: **Note:** Upon creating a new `person` using the `add` command, the `favourite` attribute of the `person` is set to `false` by default. + +
#### How the feature is implemented The Fav/Unfav feature is implemented via the `FavCommand` and `UnfavCommand`, which is supported by the `FavCommandParser` and `UnfavCommandParser` respectively. The `FavCommandParser` and `UnfavCommandParser` implements the `Parser` interface. -1. `LogicManager` receives the user input which is parsed by the `StaffConnectParser`. -2. After splitting the user input into `commandWord` and `arguments` based on the regex pattern of the user input, the `StaffConnectParser` invokes the `FavCommandParser`/`UnfavCommandParser` based on the `commandWord`, calling the method `parse` with `arguments` as the method arguments -3. `FavCommandParser`/`UnfavCommandParser` takes in the `args` string and parse it into with the static `ParserUtil#parseIndex(args)` function. If the `INDEX` format is invalid, a `ParseException` will be thrown. -4. `FavCommandParser`/`UnfavCommandParser` then creates the `FavCommand`/`UnfavCommand` and returns it. -5. The `LogicManager` executes the `FavCommand`/`UnfavCommand`, which creates a `Person` with the `Favourite` attribute set as `true`/`false` respectively and updates the model with this new `Person`. - -The following sequence diagram shows how the `fav` command works: +The following sequence diagrams shows how the `fav 1` command works: ![Fav Command Sequence Diagram](images/FavSequenceDiagram.png) -Similarly, how the `unfav` command works is shown below: +
:information_source: **Note:** The lifeline for `FavCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram. +
+ +1. When the user issues the command `fav 1`, `LogicManager` is called upon to execute the command, it is passed to the `StaffCommandParser` object which creates a `FavCommandParser` to parse the arguments for the `fav` command. +2. The parsing of `FavCommandParser` results in a new `FavCommand` initialized by an index `Index`. + +![Execute Fav Command Sequence Diagram](images/ExecuteFavCommandSequenceDiagram.png) + +3. When the `FavCommand` is executed, it retrieves the last shown list using `getSortedFilteredPersonList()` and creates a favourite person. This portions' details has been separated from the main sequence diagram into the reference sequence diagram below. +4. After creating a new `Person` object, `FavCommand` replaces the old `Person` object with the new one. +5. The command communicates with the `Model` when it is executed. More specifically, it calls `updateFilteredPersonList()` method using `PREDICATE_SHOW_ALL_PERSONS` which resets the view to default. +6. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `LogicManager`, to show in the `UI` component the success message that the `Person` at the given index is set as favourite. + +The below sequence diagram goes into more details on how the execution of the command creates a favourite person: + +![Fav Ref Sequence Diagram](images/FavRefSequenceDiagram.png) + +7. `FavCommand` calls the static `FavCommand#createFavPerson(personToFav)` function which calls for the static `PersonUtil#createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite)` using the `selectedPerson` and a new `Favourite` with the value `true`. +8. This static `PersonUtil#createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite)` function creates a new `Person` with the given `Favourite` and returns back to `FavCommand`. + +The following activity diagram summarizes what happens when a user executes a new `fav` command: + +![Fav Activity Diagram](images/FavActivityDiagram.png) + +Similarly, the following diagrams shows how the `unfav 1` command works: ![Unfav Command Sequence Diagram](images/UnfavSequenceDiagram.png) +
:information_source: **Note:** The lifeline for `UnfavCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram. +
+ +1. When the user issues the command `unfav 1`, `LogicManager` is called upon to execute the command, it is passed to the `StaffCommandParser` object which creates a `UnfavCommandParser` to parse the arguments for the `unfav` command. +2. The parsing of `UnfavCommandParser` results in a new `UnfavCommand` initialized by an index `Index`. + +![ExecuteUnfavCommandSequenceDiagram.png](images/ExecuteUnfavCommandSequenceDiagram.png) + +3. When the `UnfavCommand` is executed, it retrieves the last shown list using `getSortedFilteredPersonList()` and creates an unfavourite person. This portions' details has been separated from the main sequence diagram into the reference sequence diagram below. +4. After creating a new `Person` object, `UnfavCommand` replaces the old `Person` object with the new one. +5. The command communicates with the `Model` when it is executed. More specifically, it calls `updateFilteredPersonList()` method using `PREDICATE_SHOW_ALL_PERSONS` which resets the view to default. +6. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `LogicManager`, to show in the `UI` component the success message that the `Person` at the given index is remove as favourite. + +The below sequence diagram goes into more details on how the execution of the command creates an unfavourite person: + +![Unfav Ref Sequence Diagram](images/UnfavRefSequenceDiagram.png) + +7. `UnfavCommand` calls the static `UnfavCommand#createUnfavPerson(personToUnfav)` function which calls for the static `PersonUtil#createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite)` using the `selectedPerson` and a new `Favourite` with the value `false`. +8. This static `PersonUtil#createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite)` function creates a new `Person` with the given `Favourite` attribute and returns back to `UnfavCommand`. + +The following activity diagram summarizes what happens when a user executes a new `unfav` command: + +![Unfav Activity Diagram](images/UnfavActivityDiagram.png) + ### \[Proposed\] Undo/redo feature #### Proposed Implementation @@ -463,6 +537,7 @@ The following activity diagram summarizes what happens when a user executes a ne * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). * Cons: We must ensure that the implementation of each individual command are correct. + -------------------------------------------------------------------------------------------------------------------- ## **Documentation, logging, testing, configuration, dev-ops** @@ -621,6 +696,63 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli Use case resumes at step 1. + +**Use case: Add a meeting** + +**MSS** + +1. StaffConnect shows a list of persons +2. User requests to add a meeting to the specific person in the list +3. StaffConnect adds the meeting to the person with the provided details + + Use case ends. + +**Extensions** + +* 1a. The list is empty. + + Use case ends. + +* 2a. The given index is invalid. + + * 2a1. StaffConnect shows an error message. + + Use case resumes at step 1. + +* 3a. The given details for meeting is invalid. + * 3a1. StaffConnect shows an error message. + Use case resumes at step 1. + + +**Use case: Delete a meeting** + +**Precondition:** The intended meeting to delete exists and has been added before. + +**MSS** + +1. StaffConnect shows a list of persons +2. User requests to delete a meeting of a specific person in the list +3. StaffConnect deletes the specified meeting + + Use case ends. + +**Extensions** + +* 1a. The list is empty. + + Use case ends. + +* 2a. The given index for person is invalid. + + * 2a1. StaffConnect shows an error message. + + Use case resumes at step 1. + +* 2a. The given index for meeting is invalid. + * 2a1. StaffConnect shows an error message. + Use case resumes at step 1. + + ### Non-Functional Requirements 1. The app should work on any _mainstream OS_ as long as it has Java `11` or above installed. @@ -661,14 +793,14 @@ testers are expected to do more *exploratory* testing. 1. Download the jar file and copy into an empty folder - 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. + 2. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. -1. Saving window preferences +2. Saving window preferences 1. Resize the window to an optimum size. Move the window to a different location. Close the window. - 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained. + 2. Re-launch the app by double-clicking the jar file.
+ Expected: The most recent window size and location is retained. ### Deleting a person @@ -676,13 +808,13 @@ testers are expected to do more *exploratory* testing. 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list. - 1. Test case: `delete 1`
+ 2. Test case: `delete 1`
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. - 1. Test case: `delete 0`
+ 3. Test case: `delete 0`
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. - 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+ 4. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
Expected: Similar to previous. ### Saving data @@ -691,21 +823,21 @@ testers are expected to do more *exploratory* testing. 1. Prerequisites: Ensure that the `[JAR file location]/data/staffconnect.json` file is generated by running the JAR file of the app at least once. - 1. Test case: No modifications to data file after it has been generated.
+ 2. Test case: No modifications to data file after it has been generated.
In the image below shows the contents of the untouched data file: ![Before Corrupt Data File](images/beforeCorruptDataFile.png) Expected: The app should show a list of 6 persons ![Before Corrupt Data File Result](images/beforeCorruptDataFileResult.png) - 1. Test case: Invalid modification to data file.
+ 3. Test case: Invalid modification to data file.
Modify the `Favourite` attribute value to `Not avourite` (an invalid value) in the data file: ![After Corrupt Data File](images/afterCorruptDataFile.png) Expected: The app should show an empty list (no persons) ![After Corrupt Data File Result](images/afterCorruptDataFileResult.png) - 1. Test case: Valid modification to data file.
+ 4. Test case: Valid modification to data file.
Before, `Alex Yeoh` has the module `CS1101S` in the untouched data file as seen in `Test case: No modifications to data file after it has been generated`. Modify the `Module` attribute value to `CS2030S` (a valid value) in the data file: diff --git a/docs/UserGuide.md b/docs/UserGuide.md index acc7576aff8..625c8aa72ea 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -46,12 +46,12 @@ StaffConnect (SC) is a **desktop app for managing Professors' and Tutors' contac ## Navigability ### Overall UI layout -
![UI General](images/UiAnnotationsLayout.png) +
![UI Annotations Layout](images/UiAnnotationsLayout.png)
#### [UI] Persons Info -
![UI General](images/UiAnnotationsAttributes.png) +
![UI Annotations Attribute](images/UiAnnotationsAttributes.png) *Note that the availability will not be displayed in sequential order. * The values of `Module` will be displayed and stored in capital letters. * The values of [`Faculty`](#valid-faculty-values) will be stored to their full names. @@ -60,12 +60,12 @@ StaffConnect (SC) is a **desktop app for managing Professors' and Tutors' contac
#### [UI] Meeting List -
![UI General](images/UiAnnotationsMeetingList.png) +
![UI Annotations MeetingList](images/UiAnnotationsMeetingList.png)
#### [UI] Scrollbars and Menu -
![UI General](images/UiAnnotationsScrollbarsAndMenu.png) +
![UI Annotations ScrollBars](images/UiAnnotationsScrollbarsAndMenu.png) *Note that Persons List Scrollbar will open appear when the number of Persons in the list exceed the amount to be displayed by the view. *Note that the `Exit` button is in the dropdown of the `File` button. @@ -78,32 +78,32 @@ Before we get started StaffConnect offers a unique suite of UI controls for user 1. Clicking any items on the left persons list panel will allow you to select the person's attributes and meeting list to display.
Alternatively, clicking anywhere in the persons list panel then using your arrow keys to navigate and hitting enter to select would give the same result.
**Intended Behaviour:** -
Hovering the selection with mouse or arrow keys would not cause the details panel to switch to the selected person. This is to allow users to browse the persons list panel without switching. +
Hovering the selection with mouse or arrow keys would not cause the person information and meeting list panels to switch to the selected person. This is to allow users to browse the persons list panel without switching.
![Region to select the person](images/personPanelRegion.png) - + 2. There is a divider that is draggable up and down to hide and show details on the right side and to customise the look of your application.
![Region to select the divider](images/detailsDividerRegion.png) -3. Each of the 2 detail panels on the right are able to pan in all four directions to view the content: +3. The person information and meeting list panels on the right are able to pan in all four directions to view the content: - For mouse pad users, dragging around with two fingers the around would pan around the pane. - For mouse users, __[Mouse Wheel]__ will scroll up and down while __[Shift + Mouse wheel]__ will scroll left and right. - __[Left click + Drag Mouse]__ would pan around in the details pane as well. - Keyboard arrow keys are able to pan around as well, but the scroll speed may differ on different systems. - There are scroll bars at the vertical and horizontal dividers of the window pane, dragging them in the respective direction will pan around as well. - -4. The Result display:
+ +4. Command Output:
The scroll bars can only be scrolled by two ways: 1. For mouse pad users, dragging around with two fingers the around would pan around the pane. 2. For mouse users, __[Mouse Wheel]__ will scroll up and down while __[Shift + Mouse Wheel]__ will scroll left and right. 3. Simply dragging the scroll bar with a left mouse click. -
**Scrolling by arrow keys is not fully supported in the result display** +
**Scrolling by arrow keys is not fully supported in the Command Output panel** -5. The Command box:
+5. Command Line Interface:
The input can only be scrolled by __[Holding Left Click + Drag Mouse]__ to the edge in the direction to scroll. This is to allow making adjustments on very long commands.
-

+

### Alternative UI arrangements
![first alternative ui](images/firstAlternative.png)
@@ -265,10 +265,17 @@ format: `filter [m/MODULE] [f/FACULTY] [t/TAG]… [a/AVAILABILITY]…` Examples: * `filter m/CS1101S` returns `Alex Yeoh` +
![result of `filter m/CS1101S`](images/AfterFilterCommand1.png) * `filter f/Computing t/professor` returns `Alex Yeoh`, `Charlotte Oliveiro`, `David Li` and `Roy Balakrishman` +
![result of `filter f/Computing t/professor`](images/AfterFilterCommand2.png) * `filter t/tutor` returns `Bernice Yu`, `Irfan Ibrahim`
- ![result for 'filter t/tutor'](images/filterTutorTagResult.png) - + ![result for 'filter t/tutor'](images/AfterFilterCommand3.png) +* To illustrate the next example, the sample data are edited first to let `Alex Yeoh`, `Charlotte Oliveiro` and `Irfan Ibrahim` have tags `friend`, `professor` and `youtuber`. They are available on `Monday 12:00 13:00` and `Thursday 12:00 13:00`. +
![results of the above-mentioned edits](images/BeforeFilterCommand1.png) +
You can see that for `Roy Balakrishnan`, while he is available on `Monday 12:00 13:00` and `Thursday 12:00 13:00`, he does not have tags `friend` and `youtuber`. +
![Roy Balakrishnan not having other tags](images/BeforeFilterCommand2.png) +
`filter f/soc t/professor t/friend t/youtuber a/mon 12:00 13:00 a/thurs 12:00 13:00` returns `Alex Yeoh`, `Charlotte Oliveiro` and `Irfan Ibrahim`. +
![result of the command](images/AfterFilterCommand4.png)
### Sorting persons: `sort` @@ -350,19 +357,20 @@ Deletes a meeting from a person based on specified meeting index. Format: `meeting-delete INDEX i/MEETING-INDEX ` -* Deletes the meeting at specified `MEETING-INDEX` from the person at specified `INDEX`. -* The index refers to the index number shown in the displayed person list. +* Deletes the meeting at specified `MEETING-INDEX` from the person at 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,…​ and tally within range index of the displayed person list. * The meeting-index refers to the index number shown in the displayed meeting list. * The meeting-index **must be a positive integer** 1, 2, 3,…​ and tally within range index of the displayed meeting list. * The meeting from the person must exist before it can be deleted otherwise an error will be displayed. Examples: +
The following commands assumes that meetings have been added prior to the command. Otherwise, an error will be thrown.
**(Refer to the section above on how to add a meeting)** * `list` followed by `meeting-delete 1 i/1` deletes the 1st meeting from the 1st person in the list. * `meeting-delete 1 i/3` deletes the 3rd meeting from the 1st person in the current displayed contacts list. * `find Bernice Yu` followed by `meeting-delete 1 i/2` deletes the 1st meeting from the 1st person in the results of the `find` command. - +
**Results for delete meeting:**
The following command was applied: `find Bernice Yu` followed by `meeting-delete 1 i/2`.
__(Disclaimer: The content shown in the examples may not match what you have added to your own meetings within the staff book).__ @@ -462,12 +470,13 @@ This may result in possible data loss. e.g. Meetings of a person may be deleted. There will be no further prompt after entering the command to refresh meetings of all persons. This action is irreversible and the meeting information that may be deleted cannot be retrieved afterwards. -Deletes all meetings that start before the very moment the user types in the command and enters. +Deletes all meetings that start before the very moment the user types in the command and enters. Notice that only persons currently filtered in the list will be affected. Format: `refresh` * The deleted meetings will be explicitly printed again to the use, specifying content of the meeting and who "owns" the meeting. * If no meetings are deleted, there will no error thrown. Instead, a prompt will be given to user that no meeting is deleted. +* The command will not delete meetings for persons not currently shown in the list due to filter command or find command. If the user wants to execute the command for all persons, type in `list` first to show all persons. Examples: * If there is a meeting `Avengers Assemble` that happened in `31/08/1939 12:00`, when the user types in `refresh`, it will be deleted. @@ -480,7 +489,7 @@ Examples: ![After refreshing](images/AfterRefreshCommand.png) **Known limitations:** -Refresh is only used when the user decides to remove clutter in the staff book, and wants to remove outdated meetings. +Refresh is only used when the user decides to remove clutter in the staff book, and wants to remove outdated meetings. This process is not done automatically as sometimes the user would like to retain old meetings for bookkeeping purposes.
@@ -531,6 +540,7 @@ StaffConnect data are saved in the hard disk automatically after any command tha StaffConnect data are saved automatically as a JSON file `[JAR file location]/data/staffconnect.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, StaffConnect 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.
Furthermore, certain edits can cause StaffConnect to behave in unexpected ways (e.g., if a value entered is outside of the acceptable range). The application will not prompt the user if the format of the data file is incorrect, but instead provide the user with an empty staff book.
@@ -627,8 +637,8 @@ Meeting Start Time | `date` | `30/1/2024 12:12`, `2002-11-15 19:00`, `1-12-2022 **Q**: How do I transfer my data to another Computer?
**A**: Install the app in the other computer and overwrite the generated data file with the file that contains the data from your current StaffConnect device.
**Q**: Why are concurrent or past meetings allowed?
-**A**: This is to allow greater flexibility for users who wish to segregate meetings of different topics happening concurrently or users who wish to store meetings in the past for bookkeeping purposes etc.. -**Q**: Why are meeting's description with the same content but different case-sensitivity allowed? +**A**: This is to allow greater flexibility for users who wish to segregate meetings of different topics happening concurrently or users who wish to store meetings in the past for bookkeeping purposes etc..
+**Q**: Why are meeting's description with the same content but different case-sensitivity allowed?
**A**: Sometimes the user would like to have finer control over how they want to differentiate between topics, and a single capital letter could make that difference. -------------------------------------------------------------------------------------------------------------------- @@ -638,12 +648,12 @@ Meeting Start Time | `date` | `30/1/2024 12:12`, `2002-11-15 19:00`, `1-12-2022 ## Known issues 1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again. -2. **When adding/editing phone number with a descriptor**, If you try to add a number with a descriptor such as `98731094 (home)`, the application rejects this input and advise the user to only provide phone numbers with numerical values only. The phone number is not intended to store phone number descriptor but users can consider using tags such as t/homePhone as a workaround. -3. **When adding/editing name containing special characters**, If you try to add a name such as `Jason s/o William`, the application rejects this input and advise the user to only provide name with alphanumeric values only. The name is not intended to store special characters but users can consider using `so` or `son of` as a workaround. If a person's name includes special characters (characters not included in modern English) like arabic characters (such as أ, ب, ت, etc.), it should be latinized first. -4. **When adding/editing name that already exists in the staff book**, if you try to do so, an error message will be prompted, as two persons are considered the same person as long as they have the same name. It is inplausible to has two persons with the same name but other different attributes. -5. **When adding/editing venues containing space with an attribute prefix**, If you try to add a venue such as `Room 12 t/r`, the application will add a person with a venue `Room 12` and a tag `r` instead of the intended venue `Room 12 t/r`. The venue is not intended to store venues that contains a space followed by an attribute prefix but users can consider omitting the space or replace with a hyphen such as `Room 12t/r` or `Room 12-t/r` as a workaround. -6. **When generating the default file and exiting via the `Exit` button**, If you try to generate the default JSON file `[JAR file location]/data/staffconnect.json` by running the JAR file, without manipulating any data and exiting via the `Exit` button, the JSON file would not be generated. You may consider using the `exit` command via the command line interface to generate the default JSON file instead. - +2. **When adding/editing an availability to a person**, the allowed formats for time is not as flexible as typing in a meeting start date. The only allowed format is `HH:mm`. `HH` is a valid 24-hour (00-23), `mm` are valid minutes (00-59). +3. **When adding/editing phone number with a descriptor**, If you try to add a number with a descriptor such as `98731094 (home)`, the application rejects this input and advise the user to only provide phone numbers with numerical values only. The phone number is not intended to store phone number descriptor but users can consider using tags such as t/homePhone as a workaround. +4. **When adding/editing name containing special characters**, If you try to add a name such as `Jason s/o William`, the application rejects this input and advise the user to only provide name with alphanumeric values only. The name is not intended to store special characters but users can consider using `so` or `son of` as a workaround. If a person's name includes special characters (characters not included in modern English) like arabic characters (such as أ, ب, ت, etc.), it should be latinized first. +5. **When adding/editing name that already exists in the staff book**, if you try to do so, an error message will be prompted, as two persons are considered the same person as long as they have the same name. It is inplausible to has two persons with the same name but other different attributes. +6. **When adding/editing venues containing space with an attribute prefix**, If you try to add a venue such as `Room 12 t/r`, the application will add a person with a venue `Room 12` and a tag `r` instead of the intended venue `Room 12 t/r`. The venue is not intended to store venues that contains a space followed by an attribute prefix but users can consider omitting the space or replace with a hyphen such as `Room 12t/r` or `Room 12-t/r` as a workaround. +7. **When generating the default file and exiting via the `Exit` button**, If you try to generate the default JSON file `[JAR file location]/data/staffconnect.json` by running the JAR file, without manipulating any data and exiting via the `Exit` button, the JSON file would not be generated. You may consider using the `exit` command via the command line interface to generate the default JSON file instead. -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/diagrams/AddMeetingParserSequenceDiagram.puml b/docs/diagrams/AddMeetingParserSequenceDiagram.puml new file mode 100644 index 00000000000..1a8ea87dd37 --- /dev/null +++ b/docs/diagrams/AddMeetingParserSequenceDiagram.puml @@ -0,0 +1,43 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":StaffConnectParser" as StaffConnectParser LOGIC_COLOR +participant ":AddMeetingCommandParser" as AddMeetingCommandParser LOGIC_COLOR +participant "m:AddMeetingCommand" as AddMeetingCommand LOGIC_COLOR + + +end box + + +[-> LogicManager : execute("meeting-add 2 d/Finals/20/04/2024 15:00") +activate LogicManager + +LogicManager -> StaffConnectParser : parseCommand("2 d/Finals s/20/04/2024 15:00") +activate StaffConnectParser + +create AddMeetingCommandParser +StaffConnectParser -> AddMeetingCommandParser +activate AddMeetingCommandParser + +AddMeetingCommandParser --> StaffConnectParser +deactivate AddMeetingCommandParser + + +StaffConnectParser -> AddMeetingCommandParser : parse(arguments) +activate AddMeetingCommandParser +ref over AddMeetingCommandParser : parse arguments for meeting-add + + +create AddMeetingCommand +AddMeetingCommandParser -> AddMeetingCommand++ +return + +return m +destroy AddMeetingCommandParser +return m +return + +@enduml diff --git a/docs/diagrams/AddMeetingSequenceDiagram.puml b/docs/diagrams/AddMeetingSequenceDiagram.puml new file mode 100644 index 00000000000..2cc513335d2 --- /dev/null +++ b/docs/diagrams/AddMeetingSequenceDiagram.puml @@ -0,0 +1,44 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant "m:AddMeetingCommand" as AddMeetingCommand LOGIC_COLOR +participant "r:CommandResult" as CommandResult LOGIC_COLOR +participant "editedPerson:Person " as editedPerson LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":ModelManager" as Model MODEL_COLOR +end box + + +[-> AddMeetingCommand : execute(model) +activate AddMeetingCommand + +AddMeetingCommand -> Model : getSortedFilteredPersonList() +activate Model +return + +ref over AddMeetingCommand : copy selectedPerson + +AddMeetingCommand -> editedPerson : addMeeting() +activate editedPerson +return + +AddMeetingCommand -> editedPerson : updateSortedMeetingList(MEETING_DATE_THEN_DESCRIPTION_COMPARATOR); +activate editedPerson +return + +AddMeetingCommand -> Model : setPerson(selectedPerson, editedPerson) +activate Model +return + +create CommandResult +AddMeetingCommand -> CommandResult++ +return + +return r + + +@enduml diff --git a/docs/diagrams/AddParserRefrenceDiagram.puml b/docs/diagrams/AddParserRefrenceDiagram.puml new file mode 100644 index 00000000000..61ec6d93738 --- /dev/null +++ b/docs/diagrams/AddParserRefrenceDiagram.puml @@ -0,0 +1,37 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +mainframe **sd** parse arguments for meeting-add + +box Logic LOGIC_COLOR_T1 +participant ":AddMeetingCommandParser" as AddMeetingCommandParser LOGIC_COLOR +participant "<>\nParserUtil" as ParserUtil LOGIC_COLOR +participant ":MeetingDescription" as MeetingDescription LOGIC_COLOR +participant ":MeetingDateTime" as MeetingDateTime LOGIC_COLOR +end box + + + +AddMeetingCommandParser -> ParserUtil : parseIndex() +activate AddMeetingCommandParser +activate ParserUtil +return + +AddMeetingCommandParser -> ParserUtil : parseDescription() +activate ParserUtil + +create MeetingDescription +ParserUtil -> MeetingDescription++ +return +return + +AddMeetingCommandParser -> ParserUtil : parseDateTime() +activate ParserUtil +create MeetingDateTime +ParserUtil -> MeetingDateTime++ +return +return + + +@enduml diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 654290ec9b1..f9e7137d155 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -24,4 +24,5 @@ Person *--> Module Person *--> Faculty Person *--> Venue Person *--> "*" Availability +Person *--> Favourite @enduml diff --git a/docs/diagrams/DeleteMeetingParserSequenceDiagram.puml b/docs/diagrams/DeleteMeetingParserSequenceDiagram.puml new file mode 100644 index 00000000000..14743451250 --- /dev/null +++ b/docs/diagrams/DeleteMeetingParserSequenceDiagram.puml @@ -0,0 +1,48 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":StaffConnectParser" as StaffConnectParser LOGIC_COLOR +participant ":DeleteMeetingCommandParser" as deleteMeetingCommandParser LOGIC_COLOR +participant "<>\nParserUtil" as ParserUtil LOGIC_COLOR +participant "d:DeleteMeetingCommand" as AddMeetingCommand LOGIC_COLOR +end box + + +[-> LogicManager : execute("meeting-delete 1 i/1") +activate LogicManager + +LogicManager -> StaffConnectParser : parseCommand("meeting-delete 1 i/1") +activate StaffConnectParser + +create deleteMeetingCommandParser +StaffConnectParser -> deleteMeetingCommandParser +activate deleteMeetingCommandParser + +deleteMeetingCommandParser --> StaffConnectParser +deactivate deleteMeetingCommandParser + +StaffConnectParser -> deleteMeetingCommandParser : parse("1 i/1") +activate deleteMeetingCommandParser + + +deleteMeetingCommandParser -> ParserUtil : parse person index +activate ParserUtil +return + +deleteMeetingCommandParser -> ParserUtil : parse meeting index +activate ParserUtil +return + +create AddMeetingCommand +deleteMeetingCommandParser -> AddMeetingCommand++ +return + +return d +destroy deleteMeetingCommandParser +return d +return + +@enduml diff --git a/docs/diagrams/DeleteMeetingSequenceDiagram.puml b/docs/diagrams/DeleteMeetingSequenceDiagram.puml new file mode 100644 index 00000000000..0904618b331 --- /dev/null +++ b/docs/diagrams/DeleteMeetingSequenceDiagram.puml @@ -0,0 +1,42 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant "d:DeleteMeetingCommand" as DeleteMeetingCommand LOGIC_COLOR +participant "r:CommandResult" as CommandResult LOGIC_COLOR +participant "editedPerson:Person " as editedPerson LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":ModelManager" as Model MODEL_COLOR +end box + +[-> DeleteMeetingCommand : execute(model) +activate DeleteMeetingCommand + +DeleteMeetingCommand -> Model : getSortedFilteredPersonList() +activate Model +return + +ref over DeleteMeetingCommand : copy selectedPerson + +DeleteMeetingCommand -> editedPerson : removeMeeting() +activate editedPerson +return + +DeleteMeetingCommand -> editedPerson : updateSortedMeetingList(MEETING_DATE_THEN_DESCRIPTION_COMPARATOR); +activate editedPerson +return + +DeleteMeetingCommand -> Model : setPerson(selectedPerson, editedPerson) +activate Model +return + +create CommandResult +DeleteMeetingCommand -> CommandResult++ +return + +return r + +@enduml diff --git a/docs/diagrams/ExecuteFavCommandSequenceDiagram.puml b/docs/diagrams/ExecuteFavCommandSequenceDiagram.puml new file mode 100644 index 00000000000..65eb0f678b6 --- /dev/null +++ b/docs/diagrams/ExecuteFavCommandSequenceDiagram.puml @@ -0,0 +1,42 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "f:FavCommand" as FavCommand LOGIC_COLOR +participant "r:CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":ModelManager" as Model MODEL_COLOR +end box + +activate LogicManager + +LogicManager -> FavCommand : execute(model) +activate FavCommand + +FavCommand -> Model : getSortedFilteredPersonList() +activate Model +return + +ref over FavCommand : create a favourite person + +FavCommand -> Model : setPerson(personToFav, favPerson) +activate Model +return + +FavCommand -> Model : updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS) +activate Model +return + +create CommandResult +FavCommand -> CommandResult++ +return + +return r +[<- LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/ExecuteUnfavCommandSequenceDiagram.puml b/docs/diagrams/ExecuteUnfavCommandSequenceDiagram.puml new file mode 100644 index 00000000000..03d76deb811 --- /dev/null +++ b/docs/diagrams/ExecuteUnfavCommandSequenceDiagram.puml @@ -0,0 +1,42 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "u:UnfavCommand" as UnfavCommand LOGIC_COLOR +participant "r:CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":ModelManager" as Model MODEL_COLOR +end box + +activate LogicManager + +LogicManager -> UnfavCommand : execute(model) +activate UnfavCommand + +UnfavCommand -> Model : getSortedFilteredPersonList() +activate Model +return + +ref over UnfavCommand : create an unfavourite person + +UnfavCommand -> Model : setPerson(personToUnfav, unfavPerson) +activate Model +return + +UnfavCommand -> Model : updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS) +activate Model +return + +create CommandResult +UnfavCommand -> CommandResult++ +return + +return r +[<- LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/FavActivityDiagram.puml b/docs/diagrams/FavActivityDiagram.puml new file mode 100644 index 00000000000..6639206ecc6 --- /dev/null +++ b/docs/diagrams/FavActivityDiagram.puml @@ -0,0 +1,23 @@ +@startuml +skin rose +skinparam ActivityFontSize 15 +skinparam ArrowFontSize 12 +start +:User executes fav command; + +'Since the beta syntax does not support placing the condition outside the +'diamond we place it as the true branch instead. + +if () then ([index is valid]) + if () then ([Person is favourite]) + :Create new Person with same values but is a favourite; + :Replace the original Person with the new one; + :Refresh the list of Persons; + else ([else]) + :Show error message to user that person is already a favourite; + endif +else ([else]) + :Show error message to user that index is invalid; +endif +stop +@enduml diff --git a/docs/diagrams/FavRefSequenceDiagram.puml b/docs/diagrams/FavRefSequenceDiagram.puml new file mode 100644 index 00000000000..c3cd6f8e638 --- /dev/null +++ b/docs/diagrams/FavRefSequenceDiagram.puml @@ -0,0 +1,31 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +mainframe **sd** create a favourite person + +box Logic LOGIC_COLOR_T1 +participant "f:FavCommand" as FavCommand LOGIC_COLOR +participant FavCommand as FavCommand1 <> LOGIC_COLOR +participant "<>\nPersonUtil" as PersonUtil LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Person" as Person MODEL_COLOR +end box + +FavCommand -> FavCommand1 : createFavPerson(personToFav) +activate FavCommand +activate FavCommand1 + +FavCommand1 -> PersonUtil : createPersonWithFavouriteStatus(selectedPerson, favourite) +activate PersonUtil + +create Person +PersonUtil -> Person++ +return createdPerson + +return favPerson +return favPerson + +@enduml diff --git a/docs/diagrams/FavSequenceDiagram.puml b/docs/diagrams/FavSequenceDiagram.puml index 6ffb3c747e1..d9f105fb2a6 100644 --- a/docs/diagrams/FavSequenceDiagram.puml +++ b/docs/diagrams/FavSequenceDiagram.puml @@ -6,22 +6,13 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR participant ":StaffConnectParser" as StaffConnectParser LOGIC_COLOR participant ":FavCommandParser" as FavCommandParser LOGIC_COLOR -participant "<>\nParserUtil" as ParserUtil LOGIC_COLOR participant "f:FavCommand" as FavCommand LOGIC_COLOR -participant "r:CommandResult" as CommandResult LOGIC_COLOR -participant FavCommand as FavCommand1 <> LOGIC_COLOR -participant "<>\nPersonUtil" as PersonUtil LOGIC_COLOR end box -box Model MODEL_COLOR_T1 -participant ":ModelManager" as Model MODEL_COLOR -participant ":Person" as Person MODEL_COLOR -end box - -[-> LogicManager : execute(userInput) +[-> LogicManager : execute("fav 1") activate LogicManager -LogicManager -> StaffConnectParser : parseCommand(userInput) +LogicManager -> StaffConnectParser : parseCommand("fav 1") activate StaffConnectParser create FavCommandParser @@ -31,13 +22,9 @@ activate FavCommandParser FavCommandParser --> StaffConnectParser deactivate FavCommandParser -StaffConnectParser -> FavCommandParser : parse(args) +StaffConnectParser -> FavCommandParser : parse("1") activate FavCommandParser -FavCommandParser -> ParserUtil : parseIndex(oneBasedIndex) -activate ParserUtil -return - create FavCommand FavCommandParser -> FavCommand++ return @@ -46,39 +33,4 @@ return f destroy FavCommandParser return f -LogicManager -> FavCommand : execute(model) -activate FavCommand - -FavCommand -> Model : getSortedFilteredPersonList() -activate Model -return - -FavCommand -> FavCommand1 : createFavPerson(personToFav) -activate FavCommand1 - -FavCommand1 -> PersonUtil : createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite) -activate PersonUtil - -create Person -PersonUtil -> Person++ -return createdPerson - -return favPerson -return favPerson - -FavCommand -> Model : setPerson(personToFav, favPerson) -activate Model -return - -FavCommand -> Model : updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS) -activate Model -return - -create CommandResult -FavCommand -> CommandResult++ -return - -return r -return - @enduml diff --git a/docs/diagrams/MeetingCopyPerson.puml b/docs/diagrams/MeetingCopyPerson.puml new file mode 100644 index 00000000000..4e88729b496 --- /dev/null +++ b/docs/diagrams/MeetingCopyPerson.puml @@ -0,0 +1,26 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +mainframe **sd** copy selectedPerson + +box Logic LOGIC_COLOR_T1 +participant ":[Add/Delete]MeetingCommand" as MeetingCommand LOGIC_COLOR +participant "<>\nPersonUtil" as PersonUtil LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Person" as Person MODEL_COLOR +end box + +activate MeetingCommand +MeetingCommand -> PersonUtil : copyPerson(selectedPerson) +activate PersonUtil + +create Person +PersonUtil -> Person++ +return copiedPerson + +return copiedPerson + +@enduml diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 15b686da1d3..20834bba09e 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -3,15 +3,20 @@ skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR +skinparam Padding 3 Package Model as ModelPackage <>{ Class "<>\nReadOnlyStaffBook" as ReadOnlyStaffBook +Class "<>\nReadOnlyMeetingBook" as ReadOnlyMeetingBook Class "<>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs Class "<>\nModel" as Model Class StaffBook Class ModelManager +Class MeetingBook +Class MeetingManager Class UserPrefs +Class UniqueMeetingList Class UniquePersonList Class Person Class Name @@ -22,6 +27,7 @@ Class Faculty Class Venue Class Tag Class Availability +Class Favourite Class Meeting Class I #FFFFFF @@ -30,8 +36,9 @@ Class I #FFFFFF Class HiddenOutside #FFFFFF HiddenOutside ..> Model -StaffBook .up.|> ReadOnlyStaffBook + +StaffBook .up.|> ReadOnlyStaffBook ModelManager .up.|> Model Model .right.> ReadOnlyUserPrefs Model .left.> ReadOnlyStaffBook @@ -39,6 +46,10 @@ ModelManager -left-> "1" StaffBook ModelManager -right-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs +MeetingManager -right-> "1" MeetingBook +MeetingBook .up.|> ReadOnlyMeetingBook +MeetingBook -down->"1" UniqueMeetingList + StaffBook *--> "1" UniquePersonList UniquePersonList --> "~* all" Person Person *--> Name @@ -49,7 +60,9 @@ Person *--> Faculty Person *--> Venue Person *--> "*" Tag Person *--> "*" Availability -Person *--> "*" Meeting +Person *--> "1" MeetingManager +UniqueMeetingList *--> "*" Meeting +Person *--> Favourite Person -[hidden]up--> I UniquePersonList -[hidden]right-> I @@ -61,7 +74,9 @@ Module -[hidden]right-> Faculty Faculty -[hidden]right-> Venue Venue -[hidden]right-> Tag Tag -[hidden]right-> Availability -Availability -[hidden]right-> Meeting +Availability -[hidden]right-> Favourite + +Person -[hidden]right> MeetingManager ModelManager --> "~* filtered" Person @enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index 95473d5aa19..018fe832a7e 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -12,6 +12,7 @@ Class MainWindow Class HelpWindow Class ResultDisplay Class PersonListPanel +Class NameCard Class PersonCard Class StatusBarFooter Class CommandBox @@ -35,22 +36,26 @@ MainWindow *-down-> "1" ResultDisplay MainWindow *-down-> "1" PersonListPanel MainWindow *-down-> "1" StatusBarFooter MainWindow --> "0..1" HelpWindow +MainWindow *-down-> "1" PersonCard -PersonListPanel -down-> "*" PersonCard +PersonListPanel -down-> "*" NameCard MainWindow -left-|> UiPart ResultDisplay --|> UiPart CommandBox --|> UiPart PersonListPanel --|> UiPart -PersonCard --|> UiPart +NameCard --|> UiPart StatusBarFooter --|> UiPart HelpWindow --|> UiPart +PersonCard --|> UiPart +NameCard ..> Model PersonCard ..> Model UiManager -right-> Logic MainWindow -left-> Logic +PersonCard -[hidden]left- PersonListPanel PersonListPanel -[hidden]left- HelpWindow HelpWindow -[hidden]left- CommandBox CommandBox -[hidden]left- ResultDisplay diff --git a/docs/diagrams/UnfavActivityDiagram.puml b/docs/diagrams/UnfavActivityDiagram.puml new file mode 100644 index 00000000000..5ea7049ad97 --- /dev/null +++ b/docs/diagrams/UnfavActivityDiagram.puml @@ -0,0 +1,23 @@ +@startuml +skin rose +skinparam ActivityFontSize 15 +skinparam ArrowFontSize 12 +start +:User executes unfav command; + +'Since the beta syntax does not support placing the condition outside the +'diamond we place it as the true branch instead. + +if () then ([index is valid]) + if () then ([Person is favourite]) + :Create new Person with same values but is not a favourite; + :Replace the original Person with the new one; + :Refresh the list of Persons; + else ([else]) + :Show error message to user that person is already not a favourite; + endif +else ([else]) + :Show error message to user that index is invalid; +endif +stop +@enduml diff --git a/docs/diagrams/UnfavRefSequenceDiagram.puml b/docs/diagrams/UnfavRefSequenceDiagram.puml new file mode 100644 index 00000000000..ba3881ecb25 --- /dev/null +++ b/docs/diagrams/UnfavRefSequenceDiagram.puml @@ -0,0 +1,33 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain +skinparam ParticipantPadding 20 + +mainframe **sd** create an unfavourite person + +box Logic LOGIC_COLOR_T1 +participant "u:UnfavCommand" as UnfavCommand LOGIC_COLOR +participant UnfavCommand as UnfavCommand1 <> LOGIC_COLOR +participant "<>\nPersonUtil" as PersonUtil LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Person" as Person MODEL_COLOR +end box + + +UnfavCommand -> UnfavCommand1 : createUnfavPerson(personToUnfav) +activate UnfavCommand1 + +UnfavCommand1 -> PersonUtil : createPersonWithFavouriteStatus(selectedPerson, favourite) +activate PersonUtil + +create Person +PersonUtil -> Person++ +return createdPerson + +return unfavPerson +return unfavPerson + + +@enduml diff --git a/docs/diagrams/UnfavSequenceDiagram.puml b/docs/diagrams/UnfavSequenceDiagram.puml index b684111bfdc..8ad78116a82 100644 --- a/docs/diagrams/UnfavSequenceDiagram.puml +++ b/docs/diagrams/UnfavSequenceDiagram.puml @@ -6,22 +6,13 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR participant ":StaffConnectParser" as StaffConnectParser LOGIC_COLOR participant ":UnfavCommandParser" as UnfavCommandParser LOGIC_COLOR -participant "<>\nParserUtil" as ParserUtil LOGIC_COLOR participant "u:UnfavCommand" as UnfavCommand LOGIC_COLOR -participant "r:CommandResult" as CommandResult LOGIC_COLOR -participant UnfavCommand as UnfavCommand1 <> LOGIC_COLOR -participant "<>\nPersonUtil" as PersonUtil LOGIC_COLOR end box -box Model MODEL_COLOR_T1 -participant ":ModelManager" as Model MODEL_COLOR -participant ":Person" as Person MODEL_COLOR -end box - -[-> LogicManager : execute(userInput) +[-> LogicManager : execute("unfav 1") activate LogicManager -LogicManager -> StaffConnectParser : parseCommand(userInput) +LogicManager -> StaffConnectParser : parseCommand("unfav 1") activate StaffConnectParser create UnfavCommandParser @@ -31,13 +22,9 @@ activate UnfavCommandParser UnfavCommandParser --> StaffConnectParser deactivate UnfavCommandParser -StaffConnectParser -> UnfavCommandParser : parse(args) +StaffConnectParser -> UnfavCommandParser : parse("1") activate UnfavCommandParser -UnfavCommandParser -> ParserUtil : parseIndex(oneBasedIndex) -activate ParserUtil -return - create UnfavCommand UnfavCommandParser -> UnfavCommand++ return @@ -46,39 +33,4 @@ return u destroy UnfavCommandParser return u -LogicManager -> UnfavCommand : execute(model) -activate UnfavCommand - -UnfavCommand -> Model : getSortedFilteredPersonList() -activate Model -return - -UnfavCommand -> UnfavCommand1 : createUnfavPerson(personToUnfav) -activate UnfavCommand1 - -UnfavCommand1 -> PersonUtil : createPersonWithFavouriteStatus(Person selectedPerson, Favourite favourite) -activate PersonUtil - -create Person -PersonUtil -> Person++ -return createdPerson - -return unfavPerson -return unfavPerson - -UnfavCommand -> Model : setPerson(personToUnfav, unfavPerson) -activate Model -return - -UnfavCommand -> Model : updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS) -activate Model -return - -create CommandResult -UnfavCommand -> CommandResult++ -return - -return r -return - @enduml diff --git a/docs/images/AddMeetingParserSequenceDiagram.png b/docs/images/AddMeetingParserSequenceDiagram.png new file mode 100644 index 00000000000..cf92f1c1dcf Binary files /dev/null and b/docs/images/AddMeetingParserSequenceDiagram.png differ diff --git a/docs/images/AddMeetingSequenceDiagram.png b/docs/images/AddMeetingSequenceDiagram.png new file mode 100644 index 00000000000..6e9a22bb470 Binary files /dev/null and b/docs/images/AddMeetingSequenceDiagram.png differ diff --git a/docs/images/AddParserRefrenceDiagram.png b/docs/images/AddParserRefrenceDiagram.png new file mode 100644 index 00000000000..02df92151a8 Binary files /dev/null and b/docs/images/AddParserRefrenceDiagram.png differ diff --git a/docs/images/AfterFilterCommand1.png b/docs/images/AfterFilterCommand1.png new file mode 100644 index 00000000000..25c6b6ef8bf Binary files /dev/null and b/docs/images/AfterFilterCommand1.png differ diff --git a/docs/images/AfterFilterCommand2.png b/docs/images/AfterFilterCommand2.png new file mode 100644 index 00000000000..136cb21dcc1 Binary files /dev/null and b/docs/images/AfterFilterCommand2.png differ diff --git a/docs/images/filterTutorTagResult.png b/docs/images/AfterFilterCommand3.png similarity index 100% rename from docs/images/filterTutorTagResult.png rename to docs/images/AfterFilterCommand3.png diff --git a/docs/images/AfterFilterCommand4.png b/docs/images/AfterFilterCommand4.png new file mode 100644 index 00000000000..34bf1e56f0e Binary files /dev/null and b/docs/images/AfterFilterCommand4.png differ diff --git a/docs/images/BeforeFilterCommand1.png b/docs/images/BeforeFilterCommand1.png new file mode 100644 index 00000000000..88f4a81d661 Binary files /dev/null and b/docs/images/BeforeFilterCommand1.png differ diff --git a/docs/images/BeforeFilterCommand2.png b/docs/images/BeforeFilterCommand2.png new file mode 100644 index 00000000000..bc541943e75 Binary files /dev/null and b/docs/images/BeforeFilterCommand2.png differ diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png index 7d5c76177eb..b9cb35cadc6 100644 Binary files a/docs/images/BetterModelClassDiagram.png and b/docs/images/BetterModelClassDiagram.png differ diff --git a/docs/images/DeleteMeetingParserSequenceDiagram.png b/docs/images/DeleteMeetingParserSequenceDiagram.png new file mode 100644 index 00000000000..0ea10e6a3dc Binary files /dev/null and b/docs/images/DeleteMeetingParserSequenceDiagram.png differ diff --git a/docs/images/DeleteMeetingSequenceDiagram.png b/docs/images/DeleteMeetingSequenceDiagram.png new file mode 100644 index 00000000000..6f9ae24c745 Binary files /dev/null and b/docs/images/DeleteMeetingSequenceDiagram.png differ diff --git a/docs/images/ExecuteFavCommandSequenceDiagram.png b/docs/images/ExecuteFavCommandSequenceDiagram.png new file mode 100644 index 00000000000..2f5db914e4c Binary files /dev/null and b/docs/images/ExecuteFavCommandSequenceDiagram.png differ diff --git a/docs/images/ExecuteUnfavCommandSequenceDiagram.png b/docs/images/ExecuteUnfavCommandSequenceDiagram.png new file mode 100644 index 00000000000..fea8fbe95b1 Binary files /dev/null and b/docs/images/ExecuteUnfavCommandSequenceDiagram.png differ diff --git a/docs/images/FavActivityDiagram.png b/docs/images/FavActivityDiagram.png new file mode 100644 index 00000000000..0e31b079903 Binary files /dev/null and b/docs/images/FavActivityDiagram.png differ diff --git a/docs/images/FavRefSequenceDiagram.png b/docs/images/FavRefSequenceDiagram.png new file mode 100644 index 00000000000..d3e677a1fc6 Binary files /dev/null and b/docs/images/FavRefSequenceDiagram.png differ diff --git a/docs/images/FavSequenceDiagram.png b/docs/images/FavSequenceDiagram.png index 5e665b383d1..6cf5a055565 100644 Binary files a/docs/images/FavSequenceDiagram.png and b/docs/images/FavSequenceDiagram.png differ diff --git a/docs/images/MeetingCopyPerson.png b/docs/images/MeetingCopyPerson.png new file mode 100644 index 00000000000..e4dbd8d2c06 Binary files /dev/null and b/docs/images/MeetingCopyPerson.png differ diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png index e06372b98f5..01e237053cb 100644 Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png index 11f06d68671..2476b369be7 100644 Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ diff --git a/docs/images/UnfavActivityDiagram.png b/docs/images/UnfavActivityDiagram.png new file mode 100644 index 00000000000..cf546759ff8 Binary files /dev/null and b/docs/images/UnfavActivityDiagram.png differ diff --git a/docs/images/UnfavRefSequenceDiagram.png b/docs/images/UnfavRefSequenceDiagram.png new file mode 100644 index 00000000000..71cddc2f5db Binary files /dev/null and b/docs/images/UnfavRefSequenceDiagram.png differ diff --git a/docs/images/UnfavSequenceDiagram.png b/docs/images/UnfavSequenceDiagram.png index 5ef791060d1..91675cf38c4 100644 Binary files a/docs/images/UnfavSequenceDiagram.png and b/docs/images/UnfavSequenceDiagram.png differ diff --git a/docs/team/iynixil.md b/docs/team/iynixil.md index 467a9e38bda..65a946b95f5 100644 --- a/docs/team/iynixil.md +++ b/docs/team/iynixil.md @@ -9,38 +9,29 @@ StaffConnect offers convenience and peace of mind to a struggling student with m Given below are my contributions to the project. -* **New Feature**: Added the ability to undo/redo previous commands. - * What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command. - * Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them. - * Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands. - * Credits: *{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}* +* **New Feature**: Added the ability to filter persons in staff book. + * What it does: allows the user to filter for persons with certain values in specified attributes. + * Justification: This feature improves the product significantly because a user can efficiently view the staff they want to see that possess certain characteristics (e.g. They teach a certain module) + * Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was relatively simple as it refers to the existing `find` command feature. * **New Feature**: Added a history command that allows the user to navigate to previous commands using up/down keys. -* **Code contributed**: [RepoSense link]() +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2324s2.github.io/tp-dashboard/?search=iynixil&breakdown=true&sort=groupTitle%20dsc&sortWithin=title&since=2024-02-23&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) * **Project management**: * Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub -* **Enhancements to existing features**: - * Updated the GUI color scheme (Pull requests [\#33](), [\#34]()) - * Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests [\#36](), [\#38]()) - * **Documentation**: * User Guide: - * Added documentation for the features `delete` and `find` [\#72]() - * Did cosmetic tweaks to existing documentation of features `clear`, `exit`: [\#74]() + * Added documentation for the features `Filtering persons` [\#93](https://github.com/AY2324S2-CS2103-F08-3/tp/pull/93) + * Added warnings for the features `delete`, `meeting-delete`, `clear`, `refresh` [\#229](https://github.com/AY2324S2-CS2103-F08-3/tp/pull/229) + * Added explanation for attributes in attribute summary table `Attribute Summary` [\#238](https://github.com/AY2324S2-CS2103-F08-3/tp/pull/238) * Developer Guide: - * Added implementation details of the `delete` feature. + * Added implementation details of the `filter` feature. [\#146](https://github.com/AY2324S2-CS2103-F08-3/tp/pull/146) + * Updated Appendix sections. [\#257](https://github.com/AY2324S2-CS2103-F08-3/tp/pull/257) * **Community**: - * PRs reviewed (with non-trivial review comments): [\#12](), [\#32](), [\#19](), [\#42]() - * Contributed to forum discussions (examples: [1](), [2](), [3](), [4]()) - * Reported bugs and suggestions for other teams in the class (examples: [1](), [2](), [3]()) - * Some parts of the history feature I added was adopted by several other class mates ([1](), [2]()) - -* **Tools**: - * Integrated a third party library (Natty) to the project ([\#42]()) - * Integrated a new Github plugin (CircleCI) to the team repo + * PRs reviewed (with non-trivial review comments): [link to all PRs reviewed by iynixil](https://github.com/AY2324S2-CS2103-F08-3/tp/pulls?q=is%3Apr+reviewed-by%3Aiynixil) + * Reported bugs and suggestions for other teams in the class: [link to all bugs found by iynixil](https://github.com/AY2324S2-CS2103T-W08-1/tp/issues?q=is%3Aissue+ped%2Fiynixil) * _{you can add/remove categories in the list above}_