PROJECT: TagLine

About the project

My team of 5 software engineering students and I were tasked with enhancing a basic command line interface desktop address book application for our Software Engineering project.

We chose to morph it into a note management application called Tagline. This enhanced application enables students to take notes easily and associate them with contacts.

Below is a screenshot of our project:

ui notes

My main role was to create a contact profile feature to display notes that are associated with a contact along with other information that are stored about the contact (e.g. email and phone number).

The following sections illustrate some more specific enhancements I have made, as well as some relevant documentation in the user and developer guides related to these enhancements.

Summary of contributions

  • Major enhancement: I added the ability for user to associate notes with contacts and display contact profile.

    • What it does:

      • User can create association between a contact and a note by tagging the note with contact or group tags that represent the contact.

      • When a user uses contact show command, there will be a view to display contact information (e.g. name and email) and all notes that are associated to that contact.

    • Justification: This feature benefits users because they can easily view all notes that are related with a contact.

    • Highlights:

      • There were challenging design decisions about the data to be stored for contact and group tags because they inherit the same tag superclass but do not have any shared attributes.

      • To standardize with note filtering implementation, the contact id that is specified through the contact show command will be translated into multiple tags that represent the contact.

      • The GUI for contact profile is like a combination of both contact and note GUIs.

  • Minor enhancement: I added a command to list all tags that have been used in Tagline.

    • What it does: Every time a user enters a valid tag, it will be recorded into the tag book which serves as a history of tags used.

    • Justification: This feature benefits forgetful users to view tags that they have used previously.

    • Highlights:

      • This enhancement added a new command type with tag as its prefix.

      • The implementation was challenging as it added additional complexity to the application to have a separate parser, command, model, and storage for tags.

    • Credits: The architecture and code of tag list command was reused and morphed from AddressBook command.

  • Code contributed: [RepoSense report]

  • Other contributions:

    • Project management:

      • Setup TravisCI (#34)

      • Initial refactoring and planning for the package structure: #6

    • Enhancements to existing features:

      • Refactor parser for contact commands: #43, #62

      • Refactor baseline structure for tag objects: #80, #145

    • Community:

      • PRs reviewed (with non-trivial review comments): #9, #68, #72, #138, #143

      • Reported bugs and suggestions for other teams in the class (examples: #19, #62)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Display the profile of a person: show

Displays a contact profile that contains information and list of notes that are associated with a given contact id.

Format:

contact show CONTACT_ID

Example:

  • Suppose you are interested to know information and notes that are associated with your contact Alex Yeoh which is stored with a contact id equals to 1 in Tagline. In addition, suppose that Tagline currently stores the following data:

    ug contactshow1
    Figure 1. List of all contacts that are stored by Tagline.
    ug contactshow2
    Figure 2. List of all groups that are stored by Tagline.
    ug contactshow3
    Figure 3. List of all notes that are stored by Tagline.
  • Instead of checking association between notes and contacts one by one, you can just enter the following command: contact show 1

    ug contactshow4
    Figure 4. Entering the command
  • This command allows you display a profile for a contact with id equals to 1. The profile contains basic information about a contact (i.e. name, email, phone number, address, and description) and list of notes that are associated with it.

    ug contactshow5
    Figure 5. Command executed, contact profile displayed

Tag a note with a contact tag

Contact tag is a tag of the form @CONTACT_ID where CONTACT_ID could be substituted with any non-negative integer with at most 8 digits.

Example: @12345, @00001, @2

By tagging a note with a contact tag, user can easily find all notes related to a certain contact.

Here is an example of tagging a note with a contact tag

  1. Enter the command note tag 1 --t @2 into the command box.

    ug notetag contacttag1
  2. Send the command and you will be able to see the tag in the note view.

    ug notetag contacttag2

List tags: list

Lists all valid tags that have ever been associated with your notes. A tag will appear in this list if it has been successfully used to tag a note previously. However, if a tag is no longer valid, it will be automatically removed from the list. Here are the conditions for a tag to be marked as invalid: - The tag is considered as a contact tag and the referenced contact is removed from Tagline. - The tag is considered as a group tag and the referenced group is removed from Tagline.

NOTE

if you untag a note, it will still appear in this list. The tag list serves as a history to remind you of tags that you can use.

Format:

tag list

Example:

  • Suppose you want to know tags that you have used previously and still valid.
    You can just use the following command: tag list.

    ug taglist1
    Figure 6. Command executed, list of tags displayed

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Contact Profile feature

Description

The user can view all notes that are associated with a certain contact with contact profile feature. A note is considered to be associated with a contact X if it satisfies one of the following criteria:

  • The note is tagged with a contact tag that represents X.

  • The note is tagged with a group tag where the represented group has X as one of its members.

This feature takes advantage of the existing note tag command by having these two types of tags:

  • Contact tag:

    • Use @ symbol as the tag prefix.

    • Represents a contact using its id.

    • Usage example: @12345. This represents a contact with id 12345.

  • Group tag:

    • Use % symbol as the tag prefix.

    • Represents a group using its name.

    • Usage example: %cs2103t. This represents a group with name cs2103t.

The user can use contact show command to display the profile of a contact. A contact profile contains all the stored information (e.g. email and address) and notes that are associated with that contact.

Implementation

The tags that represent contact and group are facilitated by the ContactTag and GroupTag classes.

Whenever a user uses note tag command to tag a note with any type of tag, part of the input that represents the value of tag (i.e. follows --t TAG format) will be passed into TagParserUtil. The parser will handle the translation based on the first non-whitespace character into a Tag object, which is possible to be either ContactTag or GroupTag.

Meanwhile, the mechanism to display a contact profile is facilitated by the ShowContactCommand class. This command takes a contact id as parameter and stores it inside the object. Upon execution, the command will ask Model for all groups that contain the given contact as one of their members. Afterward, it will filter notes based on contact id and all the group names that are converted into Tag objects.

Parsing for contact and group tags

Parsing for contact and group tags are handled by TagParserUtil as described in the tagging feature section. Differences between input format with other type of tag (i.e. hash tag) is only the first character where contact tag uses @ symbol and group tag uses % symbol.

However, the main difference is in the implementation of Tag#isValidInModel, which is an abstract method that needs to be implemented by every concrete subclass of Tag. The following are how this method is implemented in contact and note tags:

  • Contact tag determines its validity in the model by calling Model#findContact, which takes a ContactId as parameter and returns an optional object of Contact that has the specified contact id. If such contact object exists, a contact tag is considered valid.

  • Group tag determines its validity in the model by calling Model#hasGroupName, which takes a GroupName as parameter and returns a boolean whether such group name exists in the data stored by Tagline or not.

Creating the command

Given below is an example scenario where the user enters a command to show a contact profile.

Step 1: Similar to other contact commands, the user command is first passed to TaglineParser to identify its type until it finally arrives at ShowContactParser which will create the command object. The ShowContactParser also checks the input arguments to make sure it follows the basic format.

ContactShowParserDiagram
Figure 7. Sequence diagram of parsing user input string to obtain a ShowContactCommand
Executing the command

When executing of ShowContactCommand, there will be an initial check whether the provided contact id is valid or not by calling Model#findContact similar with checking validity for contact tag. If the provided contact id is invalid (e.g. non existing contact), the execution will stop and directly return a CommandResult which informs about the error.

Suppose now we only consider the contact show command that is provided with valid contact id. During execution, it will translate the contact id into ContactIdEqualsSearchIdPredicate and NoteContainsTagsPredicate objects. Afterwards, those predicate will be used to update the observable contact and note list, by calling Model#updateFilteredContactList and Model#updateFilteredNoteList.

ContactShowExecutionDiagram
Figure 8. Sequence diagram of executing contact show command.

During translation from contact id to multiple tags, the command objects will call Model#findGroupsWithMember to get all groups that contain the specified contact id as one of its members. Afterwards, it creates a single array of tags that represent all tags that are associated with the contact id.

RetrieveAssociatedTagsDiagram
Figure 9. Sequence diagram of translation from contact id into associated tags.

A successful execution of ShowContactCommand will return a CommandResult that indicates a view change into ContactProfileResultView. The result view for contact profile observes the changes on observable contact and note lists to update accordingly.


Contact Logic component

ContactLogicClassDiagram
Figure 10. Class diagram of the Contact Logic Component
  1. Contact Logic is a sub-component of Logic.

  2. TaglineParser will pass a user input that can be classified as a contact command (i.e. has "contact " prefix), to the ContactCommandParser without including the "contact" keyword, e.g. TaglineParser will only pass "create --n Bob" instead of "contact create --n Bob".

  3. ContactCommandParser identifies the type of contact command and passes the argument string to the respective command parser. For example, ContactCommandParser will pass "--n Bob" to CreateContactParser if it receives "create --n Bob" as an input.

  4. This results in a ContactCommand object which is returned to the LogicManager.

  5. The command execution can affect the ContactModel.

Given below is the Sequence Diagram for interactions within the Logic component for the execute("contact create --n Bob") API call.

ContactCreateSequenceDiagram
Figure 11. Interactions Inside the Logic Component for the contact create --n Bob Command

Tag Storage component

TagStorageClassDiagram
Figure 12. Class diagram of the Tag Storage Component

The TagStorage component,

  • can save Tag objects in json format and read it back.

  • can save the Tag Book data in json format and read it back.