- Introduction
- Setting Up
- 2.1 Prerequisites
- 2.2 Importing the Project into Eclipse
- 2.3 Configuring Checkstyle
- 2.4 Troubleshooting Project Setup
- Design
- 3.1 Architecture
- 3.2 Events-Driven Nature of the Design
- 3.3 UI Component
- 3.4 Logic Component
- 3.5 Model Component
- 3.6 Storage Component
- 3.7 Common Classes
- Implementation
- 4.1 Logging
- 4.2 Configuration
- Testing
- 5.1 Headless GUI Testing
- 5.2 Troubleshooting Failed Tests
- Dev Ops
- 6.1 Build Automation
- 6.2 Continuous Integration
- 6.3 Publishing Documentation
- 6.4 Making a Release
- 6.5 Converting Documentation to PDF Format
- 6.6 Managing Dependencies
- Appendix A: User Stories
- Appendix B: Use Cases
- 8.1 Adding a Task
- 8.2 Editing a Task
- 8.3 Deleting a Task
- 8.4 Undoing a Command
- 8.5 Redoing a Command
- 8.6 Sorting Displayed Tasks
- 8.7 Marking Task as Done
- 8.8 Filtering Tasks by Date
- 8.9 Saving to a new Location
- 8.10 Viewing Completed and Uncompleted Tasks
- 8.11 Searching for Tasks Containing Keywords
- 8.12 Updating Priority of a Task
- 8.13 Getting Help
- 8.14 Clearing all Tasks
- Appendix C: Non Functional Requirements
- Appendix D: Glossary
- Appendix E : Product Survey
DoIt is a task manager to help users to organise their busy schedules using keyboard commands. It is a written in Java and uses JavaFX for its GUI
This guide aims to help developers understand how DoIt works by describing its design and implementation. The guide is organised in a top-down fashion to give readers an overview of the entire program before diving into more detailed sections
-
JDK
1.8.0_60
or laterHaving any Java 8 version is not enough Doit 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
-
Checkstyle Plug-in 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
- Click
Project
->Properties
->Checkstyle
->Local Check Configurations
->New...
- Choose
External Configuration File
underType
- Enter an arbitrary configuration name (e.g. taskManager)
- Import checkstyle configuration file found at
config/checkstyle/checkstyle.xml
- Click OK once, go to the
Main
tab, use the newly imported check configuration - Tick and select
files from packages
, clickChange...
, and select theresources
package - Click OK twice
- Rebuild project if prompted
Note to click on the
files from packages
text after ticking in order to enable theChange...
button
Problem: Eclipse reports compile errors after new commits are pulled from Git
- Reason: Eclipse fails to recognize new files that appeared due to the Git pull
- Solution: Refresh the project in Eclipse by right clicking on the project (in Eclipse package explorer) and choosing
Gradle
->Refresh Gradle Project
Problem: Eclipse reports some required libraries are missing
- Reason: Required libraries may not have been downloaded during the project import
- Solution: Run tests using Gradle once (to refresh the libraries)
Figure 2.1.1 : Architecture Diagram
The Figure 2.1.1 above explains the high-level design of DoIt
Below is a quick overview of each component:
Main
has only one class called MainApp
. It is responsible for:
- Initializing the components in the correct sequence, and connecting them up with each other at app launch
- Shutting down the components and invoking cleanup method where necessary at shut down
Commons
represents a collection of classes used by multiple other components.Two of those classes play important roles at the architecture level:
EventsCenter
: 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 architecture)LogsCenter
: This class is used by many classes to write log messages to DoIt's log file
The rest of DoIt consists of four components:
UI
: The UI of DoItLogic
: The command executorModel
: Holding the data of DoIt in-memoryStorage
: Reading data from, and writing 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, Logic
(seen in Figure 2.1.2) defines it's API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class
Figure 2.1.2 : Class Diagram of the Logic Component
The Figure 2.1.3a below shows how the components interact for the scenario where the user issues the
command delete 1
Figure 2.1.3a : Component interactions for delete 1
command (part 1)
Note how the
Model
simply raises aTaskManagerChangedEvent
when the DoIt data are changed, instead of asking theStorage
to save the updates to the hard disk
The Figure 2.1.3b 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
Figure 2.1.3b : Component Interactions for delete 1
Command (part 2)
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
Author: Ye Huan Hui
Figure 2.2.1 : Class Diagram of the UI Component
API : Ui.java
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 DoIt and updates the UI accordingly
The UI consists of a MainWindow
that is made up of parts (e.g.CommandBox
, ResultDisplay
,TaskListPanel
, EventListPanel
,FloatingTaskListPanel
,StatusBarFooter
etc). All these, including the MainWindow
, inherit from the abstract UiPart
class
The UI
component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files found in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The CommandBox
component handles the field for user input
The UiManager
component implements Ui
interface.The UiManager
is the manager of the UI component, and it contains event handling methods
The UiPart
component is an abstract class, represents a distinct part of the UI. It contains a scene graph with a root node.
The TaskListPanel
component,EventlistPanel
component and FloatingTaskListPanel
component display TaskCard
objects in listviews
The TaskCard
component associates with each task in the observablelist, containing all attributes of the task, with images loaded on attributes like priority, existence of description
Author: Lee Jin Shun
Figure 2.3.1 : Class Diagram of the Logic Component
API : Logic.java
The Logic
component:
- Parses the user command using the
Parser
class - Creates a
Command
object which is executed by theLogicManager
- Invokes changes to the
Model
(e.g. adding a task) and/or raises events - Encapsulates a
CommandResult
object which is passed back to theUi
The Logic consists of a Parser
class which parses the user command coming from the UI
Component.
The Parser
class then calls the corresponding parser for the specific ommand, for e.g. DeleteCommandParser
.
The command parser, for this case DeleteCommandParser
will now create an instance of DeleteCommand
.
This Command
object is then executed by the LogicManager
which can invoke changes in the Model
class.
This can be done through various actions such as adding or editing a task.
Finally, the result of the command execution is encapsulated in a CommandResult
object and passed back to the UI
.
The Command
pattern is evident in this component, as you can see a request encapsulated as a object allowing you to parametrize clients with different requests.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete 1")
API call
Figure 2.3.1 : Interactions Inside the Logic Component for the delete 1
Command
Author: Hon Kean Wai
Figure 2.4.1 : Class Diagram of the Model Component
API : Model.java
The Model
component:
- Stores the user's preferences
- Stores and manages DoIt's 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) - Remains unaffected by changes in the other three components due to application of the Observer Pattern
- Interacts with the other components by raising events
The Model
class is the interface of the Model
component. It provides several APIs for the other components to retrieve and update DoIt's task list data. The organization and relationship of the various classes are represented in Figure 2.4.1
The ModelManager
implements the Model
interface. It contains a UserPrefs
object that represents the user's preferences. It also contains a TaskManager
along with a TaskManagerStack
which represents a stack of TaskManager
objects which are necessary from redo and undo commands. TaskManagerStack
is implemented as a Singleton Pattern as there should exist only one instance of it the app is running.
Each TaskManager
contains a single UniqueTaskList
object. It also provides methods that directly manipulate the data in the UniqueTaskList
A UniqueTaskList
is a list of task
objects and cannot contain duplicate tasks
The ReadOnlyTaskManager
and ReadOnlyTask
interfaces allow other classes and components, such as the UI, to access but not modify the list of tasks and their details
The TaskManagerStack
represents a stack of TaskManager objects. This stack is called by the ModelManager
whenever it receives a undo or redo command.TaskManagerStack
is implemented as a Singleton Pattern and there should exist only one instance of it every time you start DoIt
The InputStack
represents a stack valid or invalid non-empty input command the user entered into the command box of UI component. This stack is called by the CommandBox
class in UI component to output the needed input string onto the command box.InputStack
is also implemented as a Singleton Pattern as there should exist only one instance of it every time you start DoIt
Author: Chew Chia Sin
Figure 2.5.1 : Structure of the Storage Component
API : Storage.java
The Storage
component:
- Saves
UserPrefs
objects in json format and load it back - Saves the DoIt data in xml format and load it back
The Storage
class is the interface of the Storage
component. It provides several APIs for the other components to retrieve and update DoIt's task list data. The organization and relationship of the various classes are represented in Figure 2.5.1
The StorageManager
implements the Storage
interface. It contains a UserPrefsStorage
interface that references JsonUserPrefsStorage
allows storing and loading of the user's preferences in json format. It also contains a TaskManagerStorage
interface that references XmlTaskManagerStorage
that allows storing and loading of the user's DoIt data
The XmlSerializableTaskManager
is a class that converts ReadOnlyTaskManager
into a serializable object with which contains a list of XmlAdaptedTask
and a list of XmlAdaptedTag
XmlAdaptedTask
converts the Model's Task
into a JAXB-friendly adapted version
XmlAdaptedTag
converts the Model's Tag
into a JAXB-friendly adapted version
Classes used by multiple components are in the seedu.doit.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 DoItWARNING
: Can continue, but with cautionINFO
: Information showing the noteworthy actions by DoItFINE
: Details that are not usually noteworthy but may be useful in debugging (e.g. print the actual list instead of just its size)
Certain properties of DoIt can be controlled (e.g. App name, logging level) through the configuration file
(default: config.json
):
Tests can be found in the ./src/test/java
folder
In Eclipse:
- To run all tests, right-click on the
src/test/java
folder and chooseRun as
>JUnit Test
- To run a subset of tests, 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
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
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.doit.commons.UrlUtilTest
) - Integration tests that are checking the integration of multiple code units
(those code units are assumed to be working)
(e.g.seedu.doit.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.doit.logic.LogicManagerTest
)
- Unit tests targeting the lowest level methods/classes
Tests fail due to NullPointException when AssertionError is expected
- Reason: Assertions are not enabled for JUnit tests. This can happen if you are not using a recent Eclipse version. (i.e. Neon or later)
- Solution: Enable assertions in JUnit tests as described here and delete run configurations created when you ran tests earlier.
See UsingGradle.md to learn how to use Gradle for build automation
We use Travis CI and AppVeyor to perform Continuous Integration on our projects See UsingTravis.md and UsingAppVeyor.md for more details
See UsingGithubPages.md to learn how to use GitHub Pages to publish documentation to the project site
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
) - Create a new release using GitHub and upload the JAR file you created
We use Google Chrome for converting documentation to PDF format, as Chrome's PDF engine preserves hyperlinks used in webpages
Here are the steps to convert the project documentation files to PDF format:
- Make sure you have set up GitHub Pages as described in UsingGithubPages.md
- Using Chrome, go to the [GitHub Pages version (UsingGithubPages.md#viewing-the-project-site) of the documentation file
- Click on the
Print
option in Chrome's menu - Set the destination to
Save as PDF
, then clickSave
to save a copy of the file in PDF format
For the best results, use the settings indicated in Figure 5.4.1
Figure 5.4.1 : Saving documentation as PDF files in Chrome
A project often depends on third-party libraries. For example, DoIt 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:
- Include those libraries in the repo (this bloats the repo size)
- Require developers to download those libraries manually (this creates extra work for developers)
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a ... | I want to ... | So that I can... |
---|---|---|---|
* * * |
New user | Have a help command | Refer to instructions when I forget how to use DoIt |
* * * |
User | Add a task | Keep track of a task which can be done anytime |
* * * |
User | Add a task with a deadline | Keep track of a task which has to be done by a specific date and time |
* * * |
User | Add a task with start and end time | Keep track of a task which occurs during a time frame |
* * * |
User | Delete a task | Remove a task that is no longer needed |
* * * |
User | Edit a task | Update task information |
* * * |
User | Search a task by its details | Locate task easily |
* * * |
User | Set task as completed | Keep track of completed tasks |
* * * |
User | Undo the most recent action | Revert changes made |
* * * |
User | Block multiple timeslots when the timing is uncertain | Know which times are available for me to add new tasks |
* * * |
User | Set priority to a task | Know which is the highest priority that I should do first |
* * * |
User | Tag/Categorise a task | Know what to do when I am in the current context |
* * |
User | Sort tasks by date, priority, deadline, recurrence, tags | View important tasks first |
* * |
User | Select a task by index | Reduce typing needed |
* |
User | Colour scheme to represent priority | Visually differentiate between priority levels easily |
(For all use cases below, the System is the DoIt
and the Actor is the user
, unless specified otherwise)
MSS
- User enters command to add task
- System add task and shows it on the to do list
- Use case ends
Extensions 1a. The user enters a duplicate task (same name same deadline)
System shows an error message Use case ends
1b. The user enters a duplicate task but different deadline
System prompt him to reschedule Use case ends
3a. User undoes add task command
System deletes newly added task and show feedback to user Use case ends
MSS
- User enters command to edit task
- System edits task and displays feedback to user
- Use case ends
Extensions 1a. The user enters a task that is not in the System
System shows an error message Use case ends
1b. The user uses wrong syntax to edit the task
System shows example of correct syntax Resume from 1
3a. User undoes task edit command
System adds the edited task back and shows feedback to user Use case ends
MSS
- User requests to list tasks
- System shows a list of tasks
- User requests to delete a specific task in the list by its name/index
- System deletes the task
Use case ends
Extensions
2a. The list is empty
Use case ends
3a. The given name/index is invalid
3a1. System shows an error message
Use case resumes at step 2
4a. User undoes task delete command
System adds the deleted task back and shows feedback to user Use case ends
MSS
- User enters command to undo previously undoable command
- System undo previous undoable command shows feedback to user Use case ends
Extensions 1a. The user enters undo but there is no previous undoable command
System shows an error message Use case ends
3a. User redo undone command
System redo the undone command and shows feedback to user Use case ends
MSS
- User enters command to redo the previously undone command
- System redo previously undone command and shows feedback to user Use case ends
Extensions 1a. The user enters redo but there is no undone command
System shows an error message Use case ends
3a. User undo redone command
System undo the redone command and shows feedback to user Use case ends
MSS
- User enters command to sort that tasks displayed
- System marks sorts the task by what the user wants and shows feedback to user Use case ends
Extensions 1a. The user enters an invalid sort
System shows an error message Use case ends
MSS
- User enters command to mark task as done
- System marks tasks as done and shows feedback to user Use case ends
Extensions 1a. The user enters a task that is not in the System
System shows an error message Use case ends
3a. User undoes mark task done command
System marks the task back as undone and shows feedback to user Use case ends
MSS
- User enters command to filter task by date
- System filters tasks by date and shows them to user Use case ends
Extensions 1a. The user enters an invalid date
System shows an error message Use case ends
MSS
- User enters command to save data to specified location
- System saves the data and feedback to user the success Use case ends
Extensions 1a. User enters an invalid location to save
System shows an error message Use case ends
1b. User enters the current save location to save
System shows an error message Use case ends
1c. User enters a duplicated save location to save
System shows an error message Use case ends
1d. User enters invalid file name to save
System shows an error message Use case ends
MSS
- User enters command to view uncompleted or completed tasks
- System opens a new window show list of completed and uncompleted tasks Use case ends
MSS
- User enters command to view uncompleted or completed tasks
- System show tasks containing keywords Use case ends
Extensions 2a. User enters invalid task name to search
System shows an error message Use case ends
2a. User enters task name not in list
System shows an empty list Use case ends
MSS
- User enters command to update priority of task
- System updates priority to user specified priority Use case ends
Extensions 1a. User enters a task that is not in the System
System shows an error message Use case ends
1b. User enters an invalid priority
System shows an error message Use case ends
MSS
- User enters command for help
- System shows help prompt Use case ends
MSS
- User enters command to clear all tasks
- System clears all tasks Use case ends
-
Should work on any mainstream OS if has Java
1.8.0_60
or higher installed -
Should be able to hold up to 100 tasks without a noticeable sluggishness in performance for typical usage
-
Should be able to accomplish most of the tasks faster using commands than using the mouse for a user with above average typing speed for regular English text (i.e. not code, not system admin commands)
-
Should be able to enter a task in one command instead of multiple clicks
-
Should be able to access the program offline access tasks in areas without internet
-
Should be able to complete any user command within 2 seconds
-
Should delete all past tasks automatically without user doing it manually
-
Should take no more than 5 minutes for a first-time user to learn how to use program
{More to be added}
CRUD: Create, read, update and delete
GUI: Graphical user interface is the means by which information from the system is displayed to the user
Index of task: The number visually tagged to a task on the GUI (changes with how tasks are listed)
Mainstream OS: Windows, Linux, Unix, OS-X Operating Systems
MSS: Main Success Scenario of a use case
Sync: Synchronize / adjust data on multiple files to be the same as each other
Task: A to-do without a date range, and optionally has a deadline
UI: User interface is how the user and the system interact with each other
- Provides many features to use
- Provides email sync
- Tells you what to do
- Provides default settings so minimal adjustment is needed
- Allows input commands using a keyboard
- Requires too many clicks for settings and other features other than task
- Requires clicking to delete and update
- Requires internet for desktop version to use
- Functions like text document and is easy to use
- Can be navigated using keyboard only
- Starts up automatically on entering desktop
- Works offline
- Comes preinstalled on windows so no need for special IT permissions
- Unable to sync with email
- Lack of functionality(No reminders, calendar view, etc)
- Requires Windows Operating System to be installed
- Simple to use
- Nice background
- Helpful way of reminding users of pending tasks, every time user opens new tab in chrome
- Has integration with full fledged task managers like trello
- Only works with chrome browser
- Requires internet connection
- Unable to set deadline for tasks
- Minimal features
- Some shortcut keys available, good user flexibility
- CRUD can function offline
- Many features such as the ability to set reminders, due dates, recurring tasks
- Tasks are automatically sorted by due date
- Able to display completed tasks
- Well designed UI
- Not fully functional on keyboard, still need to use mouse to do operations such as select task
- Do not have an undo function
- Requires installation