- Setting Up
- Design
- Implementation
- Testing
- Dev Ops
- Appendix A: User Stories
- Appendix B: Use Cases
- Appendix C: Non Functional Requirements
- Appendix D: Glossary
- Appendix E: Product Survey
-
JDK
1.8.0_60
or laterHaving any Java 8 version is not enough.
This app will not work with earlier versions of Java 8. -
Eclipse IDE
-
e(fx)clipse plugin for Eclipse (Do the steps 2 onwards given in this page)
-
Buildship Gradle Integration plugin from the Eclipse Marketplace
- Fork this repo, and clone the fork to your computer
- Open Eclipse (Note: Ensure you have installed the e(fx)clipse and buildship plugins as given in the prerequisites above)
- Click
File
>Import
- Click
Gradle
>Gradle Project
>Next
>Next
- Click
Browse
, then locate the project's directory - Click
Finish
- If you are asked whether to 'keep' or 'overwrite' config files, choose to 'keep'.
- Depending on your connection speed and server load, it can even take up to 30 minutes for the set up to finish (This is because Gradle downloads library files from servers during the project set up process)
- If Eclipse auto-changed any settings files during the import process, you can discard those changes.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of each component.
Main
has only one class called MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connect them up with each other.
- At shut down: Shuts down the components and invoke cleanup method where necessary.
Commons
represents a collection of classes used by multiple other components.
Two of those classes play important roles at the architecture level.
EventsCentre
: This class (written using Google's Event Bus library) is used by components to communicate with other components using events (i.e. a form of Event Driven design)LogsCenter
: Used by many classes to write log messages to the App's log file.
The rest of the App consists four components.
UI
: The UI of tha 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.
Each of the four components
- Defines its API in an
interface
with the same name as the Component. - Exposes its functionality using a
{Component Name}Manager
class.
For example, the Logic
component (see the class diagram given below) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
The Sequence Diagram below shows how the components interact for the scenario where the user issues the
command delete 3
.
Note how the
Model
simply raises aTaskListChangedEvent
when the Task list data are changed, instead of asking theStorage
to save the updates to the hard disk.
The diagram below shows how the EventsCenter
reacts to that event, which eventually results in the updates
being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time.
Note how the event is propagated through the
EventsCenter
to theStorage
andUI
withoutModel
having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components.
The sections below give more details of each component.
API : Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, TaskListPanel
,
StatusBarFooter
, BrowserPanel
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class
and they can be loaded using the UiPartLoader
.
The UI
component uses 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,
- Executes user commands using the
Logic
component. - Binds itself to some data in the
Model
so that the UI can auto-update when data in theModel
change. - Responds to events raised from various parts of the App and updates the UI accordingly.
API : Logic.java
Logic
uses theParser
class to parse the user command.- This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a Task) and/or raise events. - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete 1")
API call.
API : Model.java
The Model
,
- stores a
UserPref
object that represents the user's preferences. - stores the Task List data.
- exposes a
UnmodifiableObservableList<ReadOnlyTask>
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. - does not depend on any of the other three components.
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the Task list data in xml format and read it back.
Classes used by multiple components are in the seedu.tasklist.commons
package.
We are using java.util.logging
package for logging. The LogsCenter
class is used to manage the logging levels and logging destinations.
- The logging level can be controlled using the
logLevel
setting in the configuration file (See Configuration) - The
Logger
for a class can be obtained usingLogsCenter.getLogger(Class)
which will log messages according to the specified logging level - Currently log messages are output through:
Console
and to a.log
file.
Logging Levels
SEVERE
: Critical problem detected which may possibly cause the termination of the applicationWARNING
: Can continue, but with cautionINFO
: Information showing the noteworthy actions by the AppFINE
: Details that is not usually noteworthy but may be useful in debugging. Eg. print the actual list instead of just its size
Certain properties of the application can be controlled (e.g App name, logging level) through the configuration file
(default: config.json
):
We added the undo feature to allow the user to undo his last action that modified the list of tasks. This feature uses an undo stack of UndoInfo
objects to keep track of all mutations that were made to the list of tasks in previous operations performed (commands entered). There is no limit on how many previous operations can be stored in the stack.
For this, we defined a new class called UndoInfo
that stores three objects:
- Undo ID: Integer value corresponding to the operation performed (eg. for add, this ID is 1; check UndoCommand.java for a list of all ID's)
- Filepath: String object; this is only used when the action performed was setstorage. Stores the original filepath prior to performing setstorage.
- Arraylist of tasks: This is a variable length list, with size dependent on the operation performed. For update, it stores both the new task and the original task. For clear, it stores a list of all the tasks prior to performing clear. For others like add or delete, it just stores the related task.
The information in an UndoInfo
instance is used to undo the relevant operation based on the undo ID. Example, for undoing an add operation, the task stored in the UndoInfo
object is deleted, and so on.
- Similar to undo, we have the redo operation. This operation can be used only after some changes have been undone, allowing the user to redo those actions.
- We use a redo stack to store a list of all those
UndoInfo
instances that were popped from the undo stack and pushed into this stack. These changes are redone in a manner similar to how changes are undone in Undo operation. - Note that if an operation following an undo operation mutates the list, then the redo stack is cleared at that point.
The recurring feature allows a task to recur in a specified frequency, and its dates will be updated to the next recurring date once it is marked as done. The Task
class contains information on whether this particular task is a recurring one and its relevant recurring frequency (daily, weekly, monthly or yearly). The checking and updating of a recurring task's dates occurs when the task is updated, marked as done, or when it undergoes undo and redo operations.
Tests can be found in the ./src/test/java
folder.
In Eclipse:
If you are not using a recent Eclipse version (i.e. Neon or later), enable assertions in JUnit tests as described here.
- To run all tests, right-click on the
src/test/java
folder and chooseRun as
>JUnit Test
- To run a subset of tests, you can right-click on a test package, test class, or a test and choose to run as a JUnit test.
Using Gradle:
- See UsingGradle.md for how to run tests using Gradle.
We have two types of tests:
-
GUI Tests - These are System Tests that test the entire App by simulating user actions on the GUI. These are in the
guitests
package. -
Non-GUI Tests - These are tests not involving the GUI. They include,
- Unit tests targeting the lowest level methods/classes.
e.g.seedu.tasklist.commons.UrlUtilTest
- Integration tests that are checking the integration of multiple code units
(those code units are assumed to be working).
e.g.seedu.tasklist.storage.StorageManagerTest
- Hybrids of unit and integration tests. These test are checking multiple code units as well as
how the are connected together.
e.g.seedu.tasklist.logic.LogicManagerTest
- Unit tests targeting the lowest level methods/classes.
Headless GUI Testing :
Thanks to the TestFX library we use,
our GUI tests can be run in the headless mode.
In the headless mode, GUI tests do not show up on the screen.
That means the developer can do other things on the Computer while the tests are running.
See UsingGradle.md to learn how to run tests in headless mode.
See UsingGradle.md to learn how to use Gradle for build automation.
We use Travis CI to perform Continuous Integration on our projects. See UsingTravis.md for more details.
Here are the steps to create a new release.
- Generate a JAR file using Gradle.
- Tag the repo with the version number. e.g.
v0.1
- Crete a new release using GitHub and upload the JAR file your created.
A project often depends on third-party libraries. For example, Task List depends on the
Jackson library for XML parsing. Managing these dependencies
can be automated using Gradle. For example, Gradle can download the dependencies automatically, which
is better than these alternatives.
a. Include those libraries in the repo (this bloats the repo size)
b. Require developers to download those libraries manually (this creates extra work for developers)
##Appendix A: User Stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a ... | I want to ... | So that I can... |
---|---|---|---|
* * * |
new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * |
user | add events, deadlines and [floating tasks] (#floating-tasks) | |
* * * |
user | mark a task as complete | |
* * * |
user | view events by category (overdue, today, tomorrow, next 7 days, floating, other tasks) or by date | keep track of upcoming events |
* * * |
user | view incomplete tasks | decide the next task to do |
* * * |
user | search events or tasks by keywords | view details of the event easily |
* * * |
user | edit event details | keep my task list updated |
* * * |
user | delete tasks | discard tasks that cannot be done |
* * * |
user | sort the event by date or priority | easily view events that requires immediate attention |
* * |
busy user | mark tasks as priority | display them at the top of my tasks |
* * |
busy user | have a UI panel that summarises the tasks I have | |
* * |
busy user | informed of overlapping slots | |
* * |
user | set my storage file to some other folder/directory (e.g dropbox) | store a back up of my tasks in dropbox or google drive |
* * |
user | undo and redo the changes made to my tasklist | Keep my tasklist in order |
* |
user | Have recurring events | save the trouble of having to add a new task periodically. |
* |
user | have auto-fill search | quickly search for relevant tasks |
##Appendix B: Use Cases
(For all use cases below, the System is the TaskManager
and the Actor is the user
, unless specified otherwise)
MSS
Precondition: Parameters such as date, time and keywords entered should be valid.
Guarantees:
- Event, deadline or floating task added
- User enters add command and task details with relevant parameters.
- System adds task into storage file and prints message showing the added task.
Extensions
1a. Clash of timeslots
1a1. System will identify the clash and will display to the user the list of actions to be taken. User can ignore collision or replace existing task with current task or reschedule task or cancel operation.
MSS
Precondition: Task category entered should be valid
- User enters show command and category.
- System shows list of tasks under the category entered. Use case ends.
MSS
Precondition: There has to be at least one task for the use to delete.
Guarantees:
- Event will be deleted from the storage file.
- User enters delete command and partial task name.
- System shows a list of indexed tasks matching the task name.
- User enters index number of task to be deleted.
- System deletes the task. Use case ends.
Extensions
2a. None of the existing tasks match the user input.
2a1. Use case ends.
3a. User cancels task deletion.
3a1. Use case ends.
3b. Entered index number is invalid.
3b1. System shows an error message. Use case resumes at step 2.
MSS
Precondition: Only events stored in the storage file can be searched.
- User enters find command and a keyword.
- System displays a list of matching tasks.
- User enters the index of a task from the list.
- System displays the details of the particular task.
Extensions 1a. User enters find command and an index.
1a1. Use case jumps to Step 4.
2a. The given keyword is invalid
2a1. The system shows an error message
Use case resumes at Step 1.
2b. The list is empty
Use case ends.
4a. User selects invalid task from the list
4a1. The system shows an error message
Use case resumes at Step 3.
MSS
Precondition: Task has to exist in the storage file to update.
Guarantees:
- The corresponding task details will be updated to their new values.
- The user searches for the task (UC04) to be updated.
- System displays an indexed list of the task(s).
- User enters index of task to be updated, field to be changed and the new value for the field.
- System stores updates in the storage file and prints message showing the updated entry.
Extensions
2a. The list is empty
Use case ends
3a. The given index is invalid
3a1. The system shows an error message
Use case resumes at Step 2
MSS
Precondition: The storage file has to exist in order for the directory shift to take place.
Guarantees:
- The corresponding file path will be updated to its new value.
- The user enters the file path, indicating the folder in which he wants to save the data.
- When the user enters the file path, he should indicate the file name by which he wants to update the directory: e.g Users/James/Desktop/[filename].xml
- The user can only specify the directory in which the file needs to be moved to. In this case, the file will be moved with default filename (tasklist.xml).
- System will process the file path and will create a copy of the file in the new directory.
- File in the old directory will be removed.
MSS
Precondition: The text entered by the user so far has to be the prefix of one command.
Guarantees:
- The command that matches the entered text will be autofilled.
- The user enters the first few letters of a command.
- The user presses the TAB key.
- The system finds the command matching the entered text.
- The matching command will be autofilled.
Extensions 2a. No commands match the input text
Use case ends
3a. More than one command matches the input text
Use case ends
MSS
Precondition: At least one command has been entered by the user before.
Guarantees:
- The previously entered command will be displayed.
- The user presses the UP key.
- System retrieves the previously entered command.
- The previously entered command will be displayed.
Extensions 2a. No commands were entered before the use case
Use case ends
MSS
Precondition: help command has to be entered correctly.
Guarantees:
- Command summary browser window will appear.
- Use enters 'help' in command box.
- A browser window with a list of Command summary will open.
- Press ENTER key to close the browser and return to the command line interface.
##Appendix C: Non Functional Requirements
- Should work on any Mainstream OS as long as it has Java 8 or higher installed.
- Should be able to hold up to 1000 tasks.
- Should come with automated unit tests and [open source] (#open-source) code.
- Should favor DOS style commands over Unix-style commands.
- Should not lose task/event details in the event that the App crashes.
- Should have fast response time, results added and retrieved in less than a second.
- Should not have bugs that interfere with the functionalities of the device.
- Should have back up of task data.
- Should work without requiring internet connectivity.
- Should not require an installer to run the application.
More NFRs and project constraints listed here.
##Appendix D: Glossary
Windows, Linux, Unix, OS-X.
Tasks with no specific date/time which the user might need to take note of.
Denotes software for which the original source code is made freely available, which may be redistributed and modified.
##Appendix E: Product Survey
Strengths:
- User-friendly manner of adding new events and deadlines
- Acknowledges the important features required by the project (marking a task as 'done', searching for a task by keywords, support for recurring events, quick add feature, etc.)
- Automatic reminder feature for tasks
- Categorizes events as "today", "this week" and "this month", etc. which is in line with the project requirement
- Clear, concise, responsive and efficient UI
Weaknesses:
- Does not provide support for floating tasks (need to provide a placeholder date/time while adding any task). Also not very good in recording tasks that need to be done before or after a specific date/time.
- Does not provide CLI (Command Line Interface) for managing tasks
- Too slow for users who retrieve/edit/store tasks frequently
- Unavailable in places with no internet connectivity
- Does not provide the feature to block multiple slots for unconfirmed tasks
Strengths:
- Use of natural language inputs to add events or tasks. a> Use of hashtags to categorize the tasks into their respective archives/folders. b> Input words such as everyday and every week can be used to set the timeframe for recurring events.
- There are color coded priority flags to help users decide on the priority of tasks. a> Users can filter tasks based on the priority level and a listed of task will be displayed, sorted by date.
- Tasks with no due dates can also be added and viewed.
- Apart from filters, users have an option of sorting their tasks by name, priority and date. In the homepage, there will be all the tasks displayed and users can choose their sort options to have a quick view.
- Upcoming tasks can also be filtered by their immediacy: today, next 7 days and next month.
- Comments/tags can also be added to each tasks. Sometimes, event/task name alone will not be comprehensive. Therefore, users could include description of event/task in the form of comments/tags under each event.
- A link with a list of all the shortcut keys for each function has been included.
Weaknesses:
- Reminder feature could only be utilized by premium members.
- Additional features such as backups and productivity trackers are only available in the premium version.
Strengths:
- Simple command line interface (CLI) as opposed to traditional graphical user interface (GUI).
- UNIX-style input, for those used to UNIX.
- Minimal keystrokes and taps required to speed up the process of command input
- Syncing between computer program and mobile application, for easy access to the task list for users on-the-go.
- Open-source: allows user-written extensions to be integrated. Allows powerful features to be integrated by the user.
- Ability to mark a task as a priority.
- Allows a series of tasks in a project to be listed out, for a smooth flow of work within a certain project.
- Able to set tags ("contexts") for easy reference and grouping of similar tasks together.
Weaknesses:
- CLI, which, compared to a GUI, might be more daunting to less tech-savvy users.
- Fixed format for entering dates, thus users have to remember a specific format each time they enter a date.
- No feature to search for free slots, thus users have to manually look for an empty slot before adding a task in.
Strengths:
- Uses powerful natural language for adding events with or without date.
- Keeps the calendar view and list of upcoming events active.
- Full calendar window with options to view by day, week, month or year while adding events
- Automatically shows public holidays in the calendar for easier scheduling.
- Able to sync and integrate with existing calendars e.g. local, Google and Exchange - this allows Jim to access his calendar from both his work and personal laptops.
- Supports different calendar sets.
Weaknesses:
- Does not help look for a free slot to schedule an event.
- Does not have a way to "block" multiple time slots for an event when the timing is uncertain, and release the blocked slots when the time is finalised.
- Allows scheduling for different events at the same time without prompting the user.
- No CLI.