Backend/API Developer Code Challenge
Overview
In this task, you will develop a commandline interface for working with a standard todo.txt file. (todo.txt
is a plaintext format for organizing tasks inspired by David Allen's Getting Things Done (GTD) methodology). Since the purpose of this project is primarily to demonstrate your ability to quickly learn and modify an existing codebase, we ask that you use 1set
's todotxt library, which you will need to extend to complete the list of requirements.
Format
Your program should run on a standard *nix (MacOS Terminal, Linux Shell, etc.) - or Windows PowerShell - commandline. It should accept input from a user and make appropriate modifications to a file called todo.txt
which should be stored somewhere "nearby" (i.e. in the same folder as or possibly a subfolder of the folder in which the person evaluating your code would run the program). You do not need to rely on environment variables or config files to specify the location of this file, as it's really not important to the test. It's OK to hardcode the path to the todo.txt
file.
In a *nix environment, the tester would expect to run your program in the following way:
prompt> ./todo add {task}
Command List
Your CLI should support the following commands:
ls
- lists all tasks. It should accept the following optional filter parameters:@context
- any string that starts with '@' should be interpreted as a "context tag," and the output should only include tasks with that context. If more than one "context tag" param is included, the filter should accept any todo that has one or more of the given context tagss and reject any todo lacking all of the specified context tags+project
- any string that starts with '+' should be interpreted as a "project tag," and the output should only include tasks associated with that project. If more than one "project tag" param is included, the filter should accept any todo that has one or more of the given project tags and reject any todo lacking all of the specified project tags(A)
- any string that is surrounded with()
should be interpreted as a "priority" tag, and the output should include only tasks that have the associated priority. If more than one priority tag is included in the params, the output should include all and only tasks that have any of the specified priority tags.tag:
- any string that ends in a:
should filter out any tasks that do not contain the associated tag. If more than one such string is included, the application should filter out any tasks that do not include any of the specified tags>datestring
,<datestring
- any string that starts with a>
and is inYYYY-MM-DD
format (e.g. "2021-01-01") should filter out any tasks that have due dates before the specified time. Any string that starts with a<
and is inYYYY-MM-DD
format (e.g. "2021-01-01") should filter out any tasks that have due dates after the specified time. If multiple such strings are included, it should respect the instructions of all of them (this may result in an empty list returned).|order
Any param that starts with|
should be interpreted as an ordering parameters. You can define your own list of strings for the "order" param, but you should support all the orders defined by theTaskSortByType
type in the codebase (defined here)completed
If this string is included, output completed tasks at the end of the list, subject to all the same filters, separated from the other tasks by an empty line
completed
- lists all completed tasks. It should accept the same filters asls
, with the difference that the<datestring
and>datestring
filters should apply to the "completed" date rather than the due date.add {task_string}
- adds a task to the filerm {task_id}
- removes a task from the filedo {task_id}
- mark the task specified by the id as completedtags
- list all unique tags in the file. It is not enough to simply list the tags, you have to ensure that there are no duplicates in the output.projects
- list all unique projects in the file. It is not enough to simply list the projects, you must ensure that there are no duplicates in the output.due
- output a list of unique due dates followed by the number of tasks due on that date. At the end of the list, include the number of tasks that are missing a due date. Example output:2021-03-01 16 2021-03-02 5 2021-03-15 1 26
extend {task_id} {quantity} {unit}
- Should extend the due date of the task identified by{task_id}
by{quantity}
number of{unit}
time. For example,extend 5 1 day
would add one day to the due date on task 5.extend 6 -2 week
would shorten the due date of task 6 by two weeks. So, if task 5 was due on2021-03-03
, it would be due on2021-03-04
as a result of the command. If task 6 were due on2021-03-03
, it would be due on2021-02-17
as a result of the command. If a task has no duedate when this call is made on it, it should behave as though the task were due today. You should support the following units:day
week
month
year
Other Requirements
- By default - i.e. in the absence of any other filters - output should be sorted primarily by priority, secondarily by due date, and tertiarily by created date. Completed tasks should always be listed separately (when they are listed at all)
Bonus Requirements
- Add support for
>=
and<=
as due date filters - Add a "help" or "man" page instruction that prints out instructions on how to use the app.
- For the
due
command, include the number of tasks due on the date that are not completed in parentheses. E.g.:2021-03-01 16 (8) 2021-03-02 5 (1) 2021-03-15 1 (0) 26 (22)
- Include a "TOTAL: {number}" tag at the end of the output of the
ls
command that shows the number of tasks in the output - Add terminal colors to the output. So, for example, all tasks of priority
(A)
might be yellow, the tasks of priority(B)
might be red, etc.
Fullstack API Developer Code Challenge
As an alternative, you can implement a web interface (instead of a commandline interface). This should be a REST interface to the todotxt library.
Setup - Running apichallenge.go
The basic framework has been done for you. The file apichallenge.go
implements a basic server that can handle the web connection for you (you don't need to implement authentication or user management for this task). To run this setup you will need to:
- Install
todotxt
:go get github.com/1set/todotxt
- Install
httprouter
:go get github.com/julienschmidt/httprouter
- Compile:
go build
- Run it! :
./apichallenge
Now if you navigate to http://localhost:8080/mainpage.html
you should see the main page.
Integration
You will see that the basic REST routes have been implemented for you. All you need to do is modify the relevant functions to satisfy the tasks below.
Static Assets
apichallenge.go
will serve up any file that is stored in the static/
folder as a direct path. For example, navigating to http://localhost:8080/mainpage.html
serves the mainpage.html
file. Navigating to http://localhost:8080/stylesheets/main.css
serves the main stylesheet. ETC. You can put any html or css or javascript libraries you need for the interface in the static
folder.
todo.txt
The application will load tasks from and save tasks into the provided todo.txt
file. You do not need to integrate with any kind of database. Just using this file for storage is OK.
Tasks
Be sure that you are familiar with the todo.txt file format before starting this task. Don't worry, it's easy to learn!
Your web application should support the following actions:
- List all the tasks. This part of the project should accept query parameters to filter the list of todos. The filtering must be done on the backend. The point of this part of the task is to demonstrate that you can use an existing Go codebase. So, you must implement the list filters on the backend in Go (and not on the frontend in Javascript)!!! The following query parameters should be accepted:
projects
- Any projects included here should filter the output to include only those tasks that are associated with one or more of the given projects.priority
- Any priorities included here should filter the output to include only those tasks that have one of the priorities in questioncontext
- Any contexts included here should filter the output to include only those tasks that have one of the contexts in questionorder
- If the order param is set, the tasks should come back in the order specified. You should support all the orders given in the TaskSortByType) struct.duebefore
- this should accept a string representing a datetime and only return tasks that (a) have a duedate (b) which is before the date specifieddueafter
- this should accept a string representing a datetime and only return tasks that (a) have a dueate (b) which is after the date specified
- Accept input from a user and add a new todo to the list
- Update any aspect of a task. This includes:
- Adding (or removing) a project
- Adding (or removing) a context
- Setting (or changing) the priority
- Setting (or changing) the duedate
- Mark a task as complete
- (Optional) Delete a task