This project is based on AddressBook Level 3.
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI
: The UI of the App.Logic
: The command executor.Model
: Holds the data of the App in memory.Storage
: Reads data from, and writes data to, the hard disk.Commons
represents a collection of classes used by multiple other components.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1
.
Each of the four main components (also shown in the diagram above),
interface
with the same name as the Component.{Component Name}Manager
class (which follows the corresponding API interface
mentioned in the previous point.For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
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
is specified in MainWindow.fxml
The UI
component,
Logic
component.Model
data so that the UI can be updated with the modified data.Logic
component, because the UI
relies on the Logic
to execute commands.Model
component, as it displays Person
object residing in the Model
.API : Logic.java
Here's a (partial) class diagram of the Logic
component:
The sequence diagram below illustrates the interactions within the Logic
component, taking execute("delete John Doe")
API call as an example.
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic
component works:
Logic
is called upon to execute a command, it is passed to an AddressBookParser
object which in turn creates a parser that matches the command (e.g., DeleteCommandParser
) and uses it to parse the command.Command
object (more precisely, an object of one of its subclasses e.g., DeleteCommand
) which is executed by the LogicManager
.Model
when it is executed (e.g. to delete a person).Model
) to achieve.CommandResult
object which is returned back from Logic
.Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
AddressBookParser
class creates an XYZCommandParser
(XYZ
is a placeholder for the specific command name e.g., AddCommandParser
) which uses the other classes shown above to parse the user command and create a XYZCommand
object (e.g., AddCommand
) which the AddressBookParser
returns back as a Command
object.XYZCommandParser
classes (e.g., AddCommandParser
, DeleteCommandParser
, ...) inherit from the Parser
interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model
component,
Person
objects (which are contained in a UniquePersonList
object) and all Tag
objects (which are contained in a UniqueTagList
object).UniqueTagList
object storing EventTags.
UniqueTagList
class involves the use of generics to allow it to store both Tag
and EventTag
objects.UniqueTagList<Tag>
and a list of event tags of type UniqueTagList<EventTag>
. However PlantUML is unable to capture the Person
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person>
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.UserPref
object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref
objects.Model
represents data entities of the domain, they should make sense on their own without depending on other components)API : Storage.java
The Storage
component,
AddressBookStorage
and UserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed).Model
component (because the Storage
component's job is to save/retrieve objects that belong to the Model
)Classes used by multiple components are in the seedu.addressbook.commons
package.
This section describes some noteworthy details on how certain features are implemented.
As student leaders will be in charge of multiple events, they encounter a large number of contacts to be saved. By incorporating a delete feature in EventBook to allow student leaders to swiftly delete contacts either by name or index, it streamlines their workflow, sparing them the effort of manually sifting through extensive contact lists before deletion.
This proposed delete feature introduces the concept of deleting the contacts by either name or index.
Given below is an example usage scenario and how delete mechanism behaves at each step.
Step 1: The user launches the application. The application will be in its initial state showing the full list of contacts in the EventBook.
Step 2: The user executes delete John Doe
command to delete the person named John Doe in the EventBook.
Note: If the command fails the execution, it means that the person does not exist and an error indicating that the person is not found will be shown.
The following sequence diagram shows how a delete operation goes through the Logic
component:
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
The following activity diagram summarizes what happens when a user executes a delete command:
Aspect: How delete executes:
Alternative 1 (Proposed Choice): Delete the name from the address book.
Alternative 2: Search for the name of the person and delete the index from the address book.
As student leaders manage multiple events, they often need to update contact information swiftly within EventBook. By introducing an edit feature, student leaders can efficiently modify contact details either by name or index, enhancing their productivity and streamlining their workflow.
This proposed edit feature introduces the capability to edit contacts by either their name or index.
Given below is an example usage scenario and how edit mechanism behaves at each step.
Step 1: The user launches the application. The application will be in its initial state showing the full list of contacts in the EventBook.
Step 2: The user executes edit John Doe p/97979797
command to edit the person named John Doe with the updated phone number in the EventBook.
Note: If the command fails the execution, it means that the person does not exist and an error indication that the person is not found will be shown.
The following sequence diagram shows how an edit operation goes through the Logic
component:
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.
The following activity diagram summarizes what happens when a user executes an edit command:
The ctag
, dtag
and devent
functions allow users to create and delete Tag
and EventTag
objects that are critical for EventBook to work.
ctag
Commandctag
command is facilitated by the following set of classes:
CtagCommandParser::parse
, the user input is parsed to determine if a Tag
object or an EventTag
object is to
be created. This is done via specifying t/E-
as the prefix for an EventTag
Tag
or EventTag
object as a parameter.CtagCommand::execute
, the given object is then added to the model.dtag
Commanddtag
command is facilitated by the following set of classes:
DtagCommandParser::parse
, the user input is parsed to determine which Tag
is to be deleted.DtagCommand:execute
, the provided Tag is then deleted if it exists.devent
Commanddevent
command is facilitated by the following set of classes:
DeventCommandParser::parse
, the user input is parsed to determine which EventTag
is to be deleted.DeventCommand:execute
, the provided EventTag is then deleted if it exists.Every Tag and EventTag object that exists in the program must exist within a global Tag array. Existing functions such as
add
will support the creation of Tag objects to be added to this global Tag array.
An example usage scenario illustrates how the ctag
feature operates:
ctag Friend
, creating a new Tag object named Friend
.Friend
tag.An example usage scenario illustrates how the dtag
feature operates:
dtag Friend
, deleting the Tag object named Friend
.Friend
will be deleted from the EventBook.The assign
command allows users to assign Tags and Events to contacts within EventBook to be displayed as a label in
the main interface.
assign
command is facilitated by the following classes:
AssignCommand
which extends CommandAssignCommandParser
which extends ParserAssignCommandParser::parse
, the user input is parsed to determine the contact and the Tag / EventTag that is to
be assigned, and an AssignCommand
object is returned.AssignCommand::execute
, the Person that is specified will have the respective tags assigned to them.The assign
command only takes in the index of the person to be assigned (as specified in the GUI), as well as a list of
TAGNAME
or t/E-EVENTTAGNAME
separated by spaces.
The following are the details of AssignCommand::execute
:
AssignCommand::execute
ModelManager::hasTag
and ModelManager::hasEventTag
is called for each Tag and EventTag that is provided
to see whether the provided tags are valid.ModelManager::getFilteredPersonList
and the provided index, the Person object is retrieved.ModelManager::assign
is called to assign the respective tags to the Person.In order to allow for assignment of Tags
and EventTags
to Person
objects, Person
was modified to be mutable.
Previously, Person
was defined to be immutable such that no changes could be made to their tags or fields. With the
implementation of assign
, changes had ot be made to allow mutability of each Person
object's TagList and EventTagList.
The search by tag feature allows for easy searching of contact by tag
to view people easily. This is achieved by filtering people in the contact list with the tags
to see if they have the tag you are searching assigned to them.
SearchTagCommand::execute
, the input tag name provided by the user is checked to see it is an existing tag.ModelManager::updateTagPersonList
. This allows the filteredPersons
list to be updated to show the correct contacts.The initial parsing of the search command follows the standard parsing process for all commands. Refer to the Logic component for the sequence diagram and details.
The following are the details of the execute method of SwitchCommand:
SearchTagCommand::execute
ModelManager::hasTag
is called to check whether a tag with the given name already exists.ModelManager::updateTagPersonList
is called to update the contacts displayed with the given tag
.
This will update the filteredPersons
field of ModelManager class to only contain contacts with the particular Tag.CommandResult
object is created and this is returned by SwitchCommand::execute
which displays a success message
that a tag was created. The message is stored in the SearchTagCommand
class itself.
The event switching feature allows for easy switching between event tabs to view event members. This is achieved by the introducing event-specific filtering to EventBook.
SwitchCommand::execute
, the input tag name provided by the user is checked to see whether it is an existing event tag.EventTag
is retrieved and used to update the filteredPersons list of Model class. This allows the filteredPersons
list to be updated to show the correct contacts.currentEventTag
field in Model class is also updated to the corresponding EventTag
. This ensures that the highlighted tab in the EventPanelList switches to highlight the correct Event.The initial parsing of the switch command follows the standard parsing process for all commands. Refer to the Logic component for the sequence diagram and details.
The following are the details of the execute method of SwitchCommand:
SwitchCommand::execute
ModelManager::hasEventTag
is called to check whether an event tag with the given name already exists.ModelManager::getEventTag
is called to retrieve the event tag required.ModelManager::updateEventTagPersonList
is called with the event tag retrieved. This will update the filteredPersons
field of ModelManager class to only contain contacts with the particular EventTag.CommandResult
object is created and this is returned by SwitchCommand::execute
. The CommandResult object is called with the retrieved EventTag.CommandResult
:In implementing this feature, CommandResult
was updated to take in an additional field EventTag
to facilitate the update of highlighted tabs for the EventListPanel
. The following are the varying inputs for this addtional field by different Commands:
CommandResult
with the corresponding EventTag
to switch to.CommandResult
with the default EventTag
.CommandResult
with null for the EventTag
field, since there is no need to change the highlighted tab when executing other commands. When executeCommand::MainWindow
is called to update the UI after the execution of a command, it checks whether the CommandResult
contains an EventTag
:
EventTag
does not exist, the highlighted tab in EventListPanel does not change.EventTag
exists, the eventListPanel is updated to highlight the correct tab:
list
command was executed, call EventListPanel::clearEventSelection
to switch highlighted tab back to All
tab.switch
command was executed, call EventListPanel::selectEvent
with the EventTag to switch highlighted tab to corresponding Event tab.The import/export commands allow one to easily share contact data. As student leaders, a common and easily accessible file format type for event contacts would be .csv. Eventbook supports the ability to import and export contacts using .csv files to facilitate fast and effective contact upload and sharing.
ExportCommand::execute
, a reference to the current model is passed to the ExportCommand::exportFile
callExportCommand::exportFile
accesses the model's Person data through model.getFilteredPersonList()
ExportCommand::exportFile
accesses their details through the respective getters (e.g.Person::getName()
)
and writes their details to a .csv file through a FileWriter objectAn example usage scenario illustrates how the export feature operates:
export
to export all contactsImportCommand
which extends CommandImportCommandParser
which extends ParserImportCommandParser::parse
, the user input is parsed to determine the path of the file to be imported,
and an ImportCommand
object is returned with the parsed path (a default path is given if none is specified)ImportCommand::execute
, a reference to the current model is passed and the following are called:
ImportCommand::parse
parses the given file and stores the data in an ArrayList
object. The dataImportCommand::checkFields
is called on the parsed data to check the fields. The field data is subsequently removedImportCommand::addPersons
uses the parsed Person data and simulates adding them to the model through the Add commandImportCommand::loadEventTags
adds and assigns EventTags to the model separately, since the Add command does not support this functionalityAn example usage scenario illustrates how the import feature operates:
import f/./import/import.csv
, with import.csv having 2 rows:
NAME,NUMBER,EMAIL,ADDRESS,EVENTS,TAGS
John,94756383,john@mail.com,NUS,Orientation,BestFriend|Cool
John
is imported into the address book, with parameters as above (He is assigned the existing EventTag Orientation as well)NAME,NUMBER,EMAIL,ADDRESS,EVENTS,TAGS
(.csv is comma delimited, so that means each field should be in their own cell)Target user profile:
Value proposition: Easy way to share project hierarchy / Manage project details and personnel / Quick onboarding of new team members
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a(n) … | I want to … | So that I can… |
---|---|---|---|
* * * | user | include tags when adding people | tag people based on their roles |
* * * | user | search by tags | find groups of people |
* * * | user | have different tagging options | keep my contacts organised and search effectively |
* * | user | delete by name OR index | manage my contacts easier |
* * | user | add contacts with partial information | keep my contacts as up to date as possible |
* * * | user | have knowledge on what event a person is involved in | keep my contacts easily |
* * | user | know details about an event, such as its time, etc | keep a clear mind on who is doing what and not get confused |
* | user | sort my tags based on event (and subsequently role) | visualise my contacts in a neat way |
* * | user | have a space to write notes for each contact | note my thoughts in an organised way |
* * | user proficient in CLI | have short form commands | use the programme faster |
* * | user | import details from different file types | quickly and efficiently input data |
* * | user | assign people different tags at any time | have a dynamic user experience in managing my contacts |
* * | user | save my event details in different formats | move my data to another place if needed |
(For all use cases below, the System is the EventBook
and the Actor is the user
, unless specified otherwise)
Use case 1: Delete a person
MSS
User requests to list persons
EventBook shows a list of persons
User requests to delete a specific person in the list
EventBook deletes the person
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. EventBook shows an error message.
Use case resumes at step 2.
Use case 2: Add a person
MSS
User adds person to EventBook
EventBook shows a list of persons with added person
Use case ends.
Extensions
1a1. EventBook shows an error message.
Use case ends.
Use case 3: Search by tag
MSS
User requests a search based on tag options
EventBook shows a list of persons with given tag options
Use case ends.
Extensions
1a. The given tag options are invalid.
1a1. EventBook shows an error message.
Use case ends.
2a. The list is empty.
Use case ends.
11
or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Initial launch
Download the latest EventBook.jar
file from here and copy into an empty folder
Open a command terminal and cd
into the folder with EventBook.jar
. Execute the following command to run Eventbook
:
java -jar EventBook.jar
Saving window preferences
Resize the window to an optimum size. Move the window to a different location. Close the window.
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
Shut Down
Exit
option.exit
into the Command Box and click enter.Test Cases:
add n/Alice Smith p/98765432 e/alice@gmail.com a/123 Main Street
add n/Bob Johnson p/98675423 e/bob@gmail.com a/456 Elm Street t/logistics t/head
add n/Carol Lee p/8765432109
add n/Alice Smith p/98765432 e/alice@gmail.com a/123 Main Street
Prerequisites:
list
command to display all contacts in your EventBook.edit 1 n/John Doe p/91234567 e/johndoe@example.com
edit John Doe t/publicity
edit 0 n/John Smith
edit John t/logistics
Prerequisites:
list
command to display all contacts in your EventBook.
Test Cases:find John
find john
find Alice Bob
find Bo
Prerequisites:
list
command to display all contacts in your EventBook.delete 1
delete Alice
delete 0
delete Bo
import f/./import/import.csv
import f/
import f/./import/import.csv
export
ctag Friend
ctag Good Friends
ctag Friend
ctag t/E-Orientation dc/ORIENTATION! sd/2024-04-15 10:00:00 ed/2024-04-15 12:00:00
ctag t/E-Team Meeting sd/2024-04-15 10:00:00 ed/2024-04-15 12:00:00
ctag t/E-Orientation dc/ORIENTATION! sd/2024-04-15 14:00:00 ed/2024-04-15 16:00:00
Prerequisites:
Friend
exists in EventBook.list
command to display all contacts in your EventBook.dtag Friend
dtag test
dtag
Prerequisites:
Orientation
exists in EventBook.list
command to display all contacts in your EventBook.devent Orientation
devent test
devent ori ntation
Prerequisites:
logistics
exists in EventBook.list
command to display all contacts in your EventBook.assign 1 t/logistics
logistics
.assign John t/E-Rag
Rag
.assign 1 t/hello
assign 1 t/E-hello
Prerequisites:
ctag test
assign 1 test
assign 2 test
list
command to display all contacts in your EventBook.search test
test
have been found. Contacts displayed all contain the blue test
tag.search hello
test
found.Prerequisites:
Rag
exists in EventBook.list
command to display all contacts in your EventBook.switch Rag
All
to Rag
and all contacts displayed contain the Rag
tag. The details of Rag
event are also displayed in the command result box.list
All
tab and all contacts in EventBook displayed.switch hello
Note: The switch command only takes in alphanumeric characters for the name!
Team Size: 5
ctag
command: When creating event tags with the ctag
command,
you will not get notified correctly on why you failed when you input the incorrect time(like 25:73:74 in the 24-hour
format). We plan to make the error message also mention why failed and the reason for the failure: Incorrect time input: please check that your time is correct!
delete
command updates with spacing: When displaying an error message prompting you to
input with the correct format for the delete
command, the example given displays: Example: delete 1ordelete JohnDoe
.
We plan to fix it to Example: delete 1 or delete JohnDoe
.int
which can create some issues. We plan to make the phone number we add to
contact only valid phone numbers types like +65 8888 8888 in singapore or +1 (123) 123-1234 in the United States.ctag
command:
All tags and event tags in this app are strictly one word only with and alphanumeric only(a-z, A-Z, 0-9).
When a person attempts to create tag or event tag with more than one word or contains illegal alphabet,
he/she currently will only get an error message that is not related what caused the command to fail. We plan to create an
custom error that will inform the user to that tag/event tag need to be one word with legal characters(a-z, A-Z, 0-9) only
when this mistake by the user occurs.taglist
command: The current implementation does not allow you to see all the existing tags
within the EventBook and this will cause some trouble for the user. For example, according to the user guide, when assigning a tag in the address book to a specified person,
the provided tag(s) must already exist in the EventBook. However, there is no accessible list of tags (not event tags) that have been added.
The absence of tag visibility aside from the ones you see beside contact panels in the app makes it challenging for users
to remember if a tag was added when there are too many tags in the contact. We plan to create a new command that will
display all the tags that are in the address book with a command called taglist
. For example, if I input taglist
,
the app will display all the existing tags in the EventBook, with an output like Tags: Tag1, Tag2, Tag3, Tag4
.