Overview
Notably is a note-taking desktop app, optimized for those who prefer to work with a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). It aims to help NUS tech-savvy students to get their notes taken down faster than using traditional GUI apps.
Summary of contributions
-
Major enhancement: Suggestion Engine
-
What it does:
SuggestionEngine
actively gives users an updated list of suggestions of notes as the users key in their input. Furthermore, it displays a response text to enable users to understand the meaning behind their inputted command. -
Justification:
SuggestionEngine
plays a pivotal role in providing a seamless user experience. This feature is curated for our target users (NUS tech-savvy students) who often have a large number of notes and thus may find difficulty traversing all of their notes to get to a particular note. This is whereSuggestionEngine
comes in by giving a list of suggestions of the notes that the users want to open or delete, just by typing the first few characters of their intended note. -
Highlights:
-
The
SuggestionEngine
also provides a command input line auto-fill feature. When the user presses the↓
(down arrow) button to select a suggestion, followed byEnter
, the command input line will be auto-filled with the suggestion. -
It displays response text and suggestions (if any) for all available valid commands in Notably. The implementation was quite challenging as different commands require different implementation.
-
-
-
Major enhancement: Search feature
-
What it does: The Search feature searches the occurrences of a keyword in all of the notes, and not just the currently opened one. It can also search for partial or incomplete word of the note’s content and count the number of times the keyword appears in the note. It then displays the list of suggestions of notes to the users with the most relevant search result at the top of the list.
-
Justification: Students often remember a certain keyword from their note but can’t precisely remember where it is located. The Search feature thus gives the users convenience to find the relevant note, as suggestions are sorted based on the keyword’s highest number of occurrences. If the number of occurrences is the same, the suggestions listing will based on their respective positions in the hierarchical notes arrangement.
-
Highlights:
-
The feature is complete as it traverses through all of the notes and can even search for incomplete words, hence giving the relevant suggestions to the user even before the user has finished typing. For instance, if the user types
search lect
while actually intending to find the word "lecture", Notably will still display the list of notes which contain the word "lecture". -
When the user presses the
↓
(down arrow) button to select the suggestion followed byEnter
, the note chosen will immediately be opened. The command line input is also cleared after the user pressedEnter
in order to not clutter the UI.
-
-
-
Code contributed: [Functional code]
-
Other contributions:
-
Project management:
-
Maintained the issue tracker
-
-
Enhancements to existing features:
-
Documentation:
-
Community:
-
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. |
Find a note based on certain keywords: search
If you need to look for a note that contains a specific keyword in its content, use the search
command and Notably
will show you the search results sorted by the number of matches in the note. The note with the highest number of match will be
at the top of the list, so that you can access it faster.
Format: search [-s] KEYWORD
|
Example: Searching for the keyword "Computer science"
Let’s look for the keyword "Computer science" if it exists in any of the notes that you have saved in Notably.
search -s Computer science
If the word "Computer science" exists, a list of suggestions will be generated. This list will be sorted in descending order of the number of matches, i.e. the note with the highest number of matches will be at the top of the list, as seen in the figure below.
search
command: keyword foundLet’s say the first option /Workspace/Notably/CS2103/Project
is the note you are looking for. You may press ↓ and Enter
to open the note. The figure below illustrates how the note chosen will be opened and the command line box is cleared.
search
command: open a note with the searched keywordIf the keyword you are looking for does not exist in any of your notes, no suggestions will be generated, as seen in the figure below.
search
command: keyword not foundAuto suggestions
As you type, Notably will provide you with suggestions. You can press the keyboard ↓ button followed by Enter to select any suggestion in the list.
For example, as you type open -t Notably
, a list of suggestions will be generated as seen in the figure below.
Let’s say you would like to choose the option /Workspace/Notably/Another Note
. After pressing ↓ to reach that suggestion
and pressing Enter, the command input line will be auto-filled by the suggestion, as seen in the figure below.
If no suggestion list is generated for the command open
, delete
or search
, it means the path, title, or keyword cannot be found
anywhere in Notably, as seen in the figures below.
(Coming in v2.0) Suggestion response text when opening or deleting a parent note
Variations of path with ../
(e.g. open ../
, open Note/../Note
, etc.) will not generate a comprehensive response text.
Currently, typing open ../
will generate a response text of Open a note titled "../"
instead of Open a parent note
.
Response text
Notably also displays a response text which enables you to understand the meaning of the input you type and shows an error message when your input is invalid.
For example, if you type open /CS
, the response text will indicates that you are trying to Open a note titled "/CS"
,
as seen in the figure below.
On the other hand, if you key in an invalid command, the response text will display an error message as seen in the figure below.
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. |
SuggestionEngine
API :
SuggestionEngine.java
SuggestionEngine
gives users the meaning of the command they input and a list of notes suggestions that they want to
open, delete, or search.
-
Logic
uses theSuggestionEngine
class, to handle the user input. -
According to the command the user inputs,
SuggestionEngine
will create aXYZSuggestionArgHandler
orABCSuggestionHandler
object which implementsSuggestionArgHandler
andSuggestionHandler
interface respectively.XYZSuggestionArgHandler
are for commands that require argument parsing, i.e.open
,delete
,search
,new
, whereasABCSuggestionHandler
are for commands that do not require argument parsing, i.e.edit
,exit
,help
. -
If
SuggestionArgHandler
object is created: theresponseText
in theModel
will be updated. This case will also result in the creation ofXYZSuggestionGenerator
object (except fornew
command) which implementsSuggestionGenerator
interface.XYZSuggestionGenerator
is then executed by theSuggestionEngine
. -
If
SuggestionHandler
object is created: theresponseText
in theModel
will be updated. -
The
Model
could be affected in 2 ways:-
Update
responseText
of theModel
(by theSuggestionHandler
andSuggestionArgHandler
): for instance, the inputopen /
will set theresponseText
in theModel
as "Open a note". -
Store a list of
SuggestionItem
in theModel
(by theSuggestionGenerator
).
-
-
The UI will then be able to retrieve the
responseText
and list ofSuggestionItem
from theModel
to be displayed to the user.
Given below is the Sequence Diagram for interactions within the Logic
and Suggestion
component for the input opne /a
.
opne /a
The lifeline for OpenSuggestionArgHandler should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
Suggestion Engine
Rationale
SuggestionEngine
allows the users to traverse their notes conveniently, without having
to remember the hierarchical structure of their notes. SuggestionEngine
gives users the meaning of the command they input and a list of notes suggestions that they want to
open, delete, or search.
Current implementation
SuggestionArgHandler | SuggestionHandler | |
---|---|---|
Purpose |
Handles the arguments part of the user input and updates the |
Updates the |
Commands |
|
|
Suggestion Generation |
Yes, by |
No |
-
Logic
uses theSuggestionEngine
class, to handle the user input. -
According to the command the user inputs,
SuggestionEngine
will create aXYZSuggestionArgHandler
orABCSuggestionHandler
object which implementsSuggestionArgHandler
andSuggestionHandler
interface respectively.XYZSuggestionArgHandler
are for commands that require argument parsing, i.e.open
,delete
,search
,new
, whereasABCSuggestionHandler
are for commands that do not require argument parsing, i.e.edit
,exit
,help
. -
If
SuggestionArgHandler
object is created: theresponseText
in theModel
will be updated. This case will also result in the creation ofXYZSuggestionGenerator
object (except fornew
command) which implementsSuggestionGenerator
interface.XYZSuggestionGenerator
is then executed by theSuggestionEngine
. -
If
SuggestionHandler
object is created: theresponseText
in theModel
will be updated. -
The
Model
could be affected in 2 ways:-
Update
responseText
of theModel
(by theSuggestionHandler
andSuggestionArgHandler
): for instance, the inputopen /
will set theresponseText
in theModel
as "Open a note". -
Store a list of
SuggestionItem
in theModel
(by theSuggestionGenerator
).
-
-
The UI will then be able to retrieve the
responseText
and list ofSuggestionItem
from theModel
to be displayed to the user.
Design considerations
Aspect 1: Design with respect to the whole architecture
-
SuggestionEngine
is segregated fromParser
in order to differentiate the logic when the user has finished typing and pressed Enter (which will be handled byParser
) in contrast to when the user presses the keyboard down button and Enter to take in the suggestion item. -
In order to keep the App’s data flow unidirectional,
SuggestionEngine
will update theresponseText
(which tells the user the meaning of his command) and the list ofSuggestionItem
into theModel
. Thus, by not showing theresponseText
and suggestions immediately to the UI,SuggestionEngine
will not interfere with theView
functionality. -
SuggestionArgHandler
,SuggestionHandler
,SuggestionGenerator
,SuggestionItem
, andSuggestionModel
are implemented as interfaces, in an attempt to make the design of theSuggestionEngine
component resilient to change.
Aspect 2: Implementation of suggestions generation
-
Alternative 1: Have a
SuggestionCommandParser
interface andSuggestionCommand
interface to parse each of the command, updateresponseText
in theModel
, and give suggestions.-
Pros: This provides a consistency for all the commands, where each command has a
XYZSuggestionCommandParser
andXYZSuggestionCommand
class. -
Cons: The
SuggestionCommandParsers
of the commands that do not require parsing of user input (edit
,exit
,help
) end up passing auserInput
argument that is not being used anywhere, which makes this design unintuitive. Moreover, since the updating of theresponseText
in theModel
can be done in eachSuggestionCommandParser
, theSuggestionCommand`s of `edit
,exit
, andhelp
end up to be redundant.
-
-
Alternative 2 (current choice): Create 2 separate interface to handle commands with input parsing and those without, and name it as a
SuggestionArgHandler
andSuggestionHandler
respectively.-
Pros: This solves the cons discussed in Alternative 1, as this design gives a separate implementation for the commands with input parsing and those without. It does not force the
Handler
to parse the user input when there is no need to. The namingHandler
also does not restrict the functionality of the interface and classes to just parse an input, but allows for a flexibility in executing other functionality such as updating theresponseText
in theModel
.
-
Use case: Search notes using the Auto-suggestion feature
MSS
-
User types in a keyword of a note’s content that he wants to open.
-
Notably lists out the relevant search results, with the most relevant at the top of the list (based on the keyword’s number of occurrences in the note).
-
User chooses one of the suggested notes.
-
Notably opens the chosen note.
Use case ends.
Extensions
-
2a. No suggestion is being generated.
-
2a1. Notably displays a response text, indicating that the user is trying to search through all of the notes using that particular keyword.
-
2a2. Since the empty suggestion conveys that the keyword cannot be found, the user enters a new data.
-
Steps 2a1-2a2 are repeated until the data entered is correct. Use case resumes from Step 3.
Use case: Open/ Delete notes using the Auto-suggestion feature
MSS
-
User types in an incomplete path or title of a note.
-
Notably lists out suggestions of notes.
-
User chooses one of the suggested notes.
-
Notably opens/ deletes the chosen note.
Use case ends.
Extensions
-
1a. Path or title contains invalid character(s) ( symbols
-
or`
)-
1a1. Notably displays a response text, indicating that the path or title is invalid.
-
1a2. User enters a new data.
-
Steps 1a1-1a2 are repeated until the data entered is correct. Use case resumes from Step 2.
-
1b. Path or title does not exist
-
1b1. Notably displays a response text, indicating that the user is trying to open/ delete the note with the particular path or title that the user inputs.
-
1b2. Notably does not generate any suggestions, which means the note cannot be found.
-
1b3. User enters a new data.
-
Steps 1b1-1b3 are repeated until the data entered is correct. Use case resumes from Step 2.
Appendix A: Instructions for Manual Testing
Given below are instructions to test the app manually.
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
Launch and Shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with a set of sample Notes. The window size may not be optimum.
-
-
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.
-
Add a new Note
-
Adding a new Note to Notably without immediately opening that Note.
-
Prerequisites: None of the child(ren) Note(s) of the currently opened Note has the same title as the new Note.
Moreover, the currently opened Note must be the directory where the user wants to store the new Note. -
Command:
new -t Notably
Expected: a new Note titled "Notably" is added to the currently opened Note. The currently opened Note (current working directory) remains the same (highlighted at the sidebar).
-
-
Adding a new Note to Notably and immediately opening that Note
-
Prerequisites: None of the child(ren) Note(s) of the currently opened Note has the same title as the new Note.
Moreover, the currently opened Note must be the directory where the user wants to store the new Note. -
Command:
new -t Notably -o
Expected: a new Note titled "Notably" is added to the currently opened Note. The currently opened Note (current working directory) is now the newly created "Notably" note (highlighted at the sidebar).
-
Open a Note
-
Opening a Note in Notably.
-
Prerequisites: The Note that is about to be opened must not be the root Note.
-
Command:
open [-t] Notably
Expected: The Note titled "Notably" will be opened, with its content being displayed in the UI. The label "Notably" at the sidebar will also be highlighted, to indicate that the Note is being opened.
-
Delete a Note
-
Deleting a Note in Notably.
-
Prerequisites: The Note that is about to be deleted must not be the root Note.
-
Command:
delete [-t] Notably
Expected: The Note titled "Notably" will be deleted. The other nested Notes inside the Note "Notably" will also be deleted.
The Note "Notably" will no longer be visible in the sidebar.
-
Edit a Note
-
Editing a Note in Notably.
-
Prerequisites: The Note that is about to be edited must not be the root Note.
The currently opened Note must be the Note that the user wants to edit. -
Command:
edit
Expected: An edit modal will pop up displaying your Note’s content in HTML format. The user can edit and save the Note by exiting that modal.
-
Search for a Note based on a keyword
-
Searching for a note by using a keyword in Notably.
-
Prerequisites: -
-
Command:
search [-s] hello
Expected: A list of suggestions will be displayed, sorted based on the number of keyword matches, i.e. the note having the highest number of "hello" in its body will be put at the top of the suggestion list.
-
Correct command
-
Correct command word in user input.
-
Prerequisites: There should exist a Note titled Notably.
-
Command: 'delete [-t] Notably'
-
Expected: The command is interpreted as a delete command by Notably.
-
-
Correct path in user input.
-
Prerequisites: There should exist a Note titled Notably.
-
Command: 'delete [-t] Notbly'
-
Expected: The command is interpreted as a delete command by Notably.
-