Tu_Du_ To open links in a new tab: Hold 'Command' + click on Mac, and 'ctrl' on Windows
- TU_DU_
Design and deploy an interactive To Do List that connects to a local JSON file to read and write user submitted tasks The project should run in a CLI, deployed via Heroku, using Python.
This project was created to expand my knowledge of the Python programming language, and to satisfy the requirements for my Portfolio Project 3 assessment at Code Institute
The goal of this app is to provide the user with an easy to use, interactive to do list, to help them be more productive throughout the day.
The app should:
- Be programmatically error free
- Be written using Python
- Handle all user input errors gracefully and appropriately
- Give clear instructions regarding use and valid inputs
- Store user inputted data in a JSON file
Some example user stories which will affect the design
"As a procrastinator, I would like to write down my daily goals to keep track of them and be more productive"
"As a tech nerd I want to see if I can create a to do list app that functions properly and validates input"
"As a developer new to Python, I would like to build my skills using a command line interface"
"As a returning user, I would like to create multitple lists to seperate my tasks into categories"
"As a returning user, I would like to save my lists for the next time I come and use the app"
"As a returning user, I would like to start again from scratch so I can create better lists now I know how to use the app"
I intend to build a to do list inspired by the app Todoist on the Apple App Store. While my app will not be anywhere near as sofisticated, I plan on using a JSON file to store the lists locally, and then use Python methods to read, write and remove data from the JSON file. To me this works in a similar fashion to connecting with a google sheets API, however having done that in the "Love Sandwiches" guided project, I thought using JSON would be an added challenge as I haven't worked with it as a separate file before.
Due to the nature of this project the wireframes are very basic. There is only one page and the design does not change across any devices, only a change in content.
I used flowcharts and bullet lists to map out how the app would work, so that I had a better idea of what needed to be done, and how I could store and call data. At first I wrote down a list of possible functions, and how they would interact with each other. This formed the base for the project, but as I progressed, I found that extra functions, or different approached needed to be taken. I used Apple's built in Notes app to do the first list mockup on iOS, and later Lucid to create the flowcharts. It has a variety of symbols and is really intuitive for beginners like me.
"As a procrastinator, I would like to write down my daily goals"
- The app allows users to create a list using the "Create New List" option, and then "Add a Tu_Du_" to add daily goals or other tasks.
"As a tech nerd, I want to create a to do list app that validates input"
- When users enter either a list name, or a Tu_Du_ name, code checks for both empty inputs, as well as whitespaces such as " " as an input. It then prints a message and loops back around for the user to try again.
"As a developer new to Python, I would like to build my skills using a command line interface"
- By completing this project, I have demonstrated my ability to create a functioning CLI app, which has taken a lot of work and research to build.
"As a returning user, I would like to create multitple lists to seperate my tasks into categories"
- Users can create as many lists as they wish and name them whatever they choose. This could include "Shopping", "Cleaning" "Work" as a few examples.
"As a returning user I would like to save my lists"
- The "Save All Lists" menu option writes all lists and tasks to the lists.json file, so on the next load, users can continue where they left off.
"As a returning user I would like to start again from scratch"
- The "Reset All Lists menu option will erase all user created lists, and load the default "Example List". This option doesn't require the user to save as it will write the changes to lists.json as well.
I am really pleased with the final result of this app. To further develop it, the following features would be very useful:
- Username and/or Password validation
- Users can currently Save or Reset lists, but should another user use the app, they could overwrite the original work.
- Completed Tasks score
- Currently users get a message once they have completed a Tu_Du_, but knowing how many they have completed in total would create a positive emotional response, giving an incentive to continue using the app
- Mouse Click support
- Currently the app relies on up/down/enter keys to choose options. PyInquirer does support mouseclicks, however with the options being so close together, I opted not to add this yet to avoid unwanted user error and frustration.
- Nested lists
- Should a user want to create a subfolder within a primary list, this could be quite useful.
A local JSON file was used to hold the lists. I went through a few iterations before landing on the current design.
I haven't used separate JSON files before, and it was something that I wanted to implement on my previous project
Sorting Hat Quiz. I first thought of using a Google Sheet to hold
the data, however as mentioned in the Initial Concept section, I was brand new to using JSON, and therefore opted to
challenge myself. The current version makes use of a nested dictionary within the "Lists" list within lists.json
The keys are the list names, and their values are a nested list of tasks or Tu-Du's. This made it easy to access the data,
and meant that the object never gets too deep.
- json
- JavaScript Object Notation, used for displaying and storing all lists and tasks. (See Data Model Section)
- time
- sleep: stalls the program for a defined time
- art
- tprint: Prints blown up strings in various fonts. I chose the default, but there are some really interesting ones!
- PyInquirer
- prompt: Define a list of questions and hand them to "Prompt" which gives back a list of "Choices" to be selected. Used for all of the menus.
- Python
- Used to create the content of the app itself.
- HTML
- Code Institute template files to create the terminal when deployed.
- CSS
- Code Institute template files to create the terminal when deployed.
- JavaScript
- Code Institute template files to create the terminal when deployed.
- Balsamiq
- Balsamiq was used to create wireframes for the project.
- PEP8 online
- An online Python code validation service.
- Heroku
- Used to deploy and host the app
- Gitpod
- IDE used for creation and version control via Github.
- Tiny PNG
- Used to compress all images features in this readme.
The specification within the project requires manual testing. I have performed multiple tests on the deployed site and during the development stage to ensure data is handled correctly and all functions are carrying out their intended actions.
Where user inputs are required, strip() has been used to test for empty inputs, or whitespace inputs.
All other functions of the app use the Prompt feature, so users can only select from a list of set inputs.
There were only 2 warnings found, one is a known error. The other is because I used the "global" keyword within a function. While not ideal practice having global variables of any kind, the keyword was necessary in order to properly update the json file, and allow the app to continue operating with the most recent data.
The warnings can be seen here:
The Python files have all been run through PEP8 online. The results are displayed here. No warnings or errors were found.
Two Python linters were used during the creation of this project.
While I found for the majority of the time they both alerted me to identical issues. They both had their individual uses to keep my code looking tidy and running properly.
-
Unwanted text appears after a prompt answer if user presses enter before prompt appears to begin with.
I'm not completely sure how to fix this, as adding something to catch the error would throw up more unwanted text. The bug itself does not negatively affect anything major. The first Prompt activates after the opening text finished, which in this instance opens the Instructions Page (which I would rather people use initially anyway.)
If a user pressed enter before any of the other prompts show, it will also choose the first option on the list. If this happens when an input is required, it will not enter the blank input.
- App wasn't deploying to Heroku properly
- Commit: 3177ccf
To fix this I had to add the installed packages to
requirements.txt
. I then made sure to do this each time I added a new library/package.
QUESTIONS
formerly namedmain_menu
only had local scope and so wasn't very repeatable
- Commit: d9f96d0
As mentioned,
main_menu
is now namedQUESTIONS
to avoid confusion with theshow_main_menu()
. Originally this was placed within the function, however I realised it wasn't very repeatable and I was having to copy/paste the entire dict to changechoices
key. I opted to make this a global variable, allowing me to editchoices
in various places, and keep the prompts unified throughout the app.
- Deciding how to read/write to
lists.json
- Commit: 705d537
- Commit: 6409c25
- Commit: 4965ebc
- Commit: 226da97
- The above commits all relate to the same issue. As I am new to using JSON files, I went through several ways
of accessing the data in
lists.json
. At first, I was usingwith open()
statements for reading, then writing dataCommit: 705d537
. This was a long winded way of doing it, as it wasn't necessary to update the list after each user change. I instead finally opted to open the file at the start of the programCommit: 6409c25
. Then write to it only when necessary, in thesave_all_lists()
andreset_all_lists()
functions. All other manipulation took place within the program, so users could still see the changesCommit: 4965ebc
,Commit: 226da97
.
- Removing unused files
- Commit: ee982ce
At various times towards the end of the project I tried to hand off functions to seperate files in an attempt
to clean up
run.py
. This resulted in several circular imports. I resolved these imports by only having the necessary code, but as you can see from the above commit, it left only 1-2 lines. I didn't think this was worth the change, and issues caused by the change, so I kept all task/list handling in run.py.
- Prompt would ask user to complete tasks even when the list was empty
- Commit: acd94e3
I added an
if not
statement to check for an empty list, and only show the relevant options if so.
- Within the
Complete a Tu_Du_
option, "Return to Main Menu" was being appended as a string to theselected_list
- Commit: f77c378 The plan here was to append a menu option so users could go back without completing a task. Thanks to testing by Maya Claveau, she found this bug, which I then fixed by adding `get_menu_options(selected_list).
save_all_lists()
&reset_all_lists()
were not updating the global variables
- Commit: a135c9b
I had not realised that the global variables I created on lines 13-15 did not update themselves when their
'parent' variable did. To fix this, I added statements to
reset_all_lists()
once I had written tolists.json
soshow_exisiting_lists()
would update the content displayed.
- Users could submit blank list or Tu_Du_
- Commit: 74f495f
- Commit: f59e6f8
- These commits add the same check to different inputs. I used the
split()
method along with a while loop to catch any empty inputs, or whitespace inputs from spaces. This will display a message for the user, then ask them to try another input.
The app was made using Github
- Sign in to GitHub.
- I used a template created by Code Institute that can be accessed here and is available for public use via the Use this template button.
This section assumes you are working from the template mentioned above, as this is the first python project I have worked on.
To install all packages within this repo you can run pip freeze
and then copy/paste
the result.
To install individual packages you need to review the appropriate
documentation for the install command. All packages I have found and used were
installed using something similar to pip install time
. The documentation
files are linked above under the python packages heading.
To run a file from the terminal I pressed the small "play button" icon in the top right corner of the screenshot to run the file.
Alternatively, you can open the file you wish to run, and type python3 file_name
in the terminal.
- Navigate to your heroku dashboard
- Click "New" and select "Create new app".
- Input a meaningful name for your app and choose the region best suited to your location.
- Select "Settings" from the tabs.
- Click "Reveal Config Vars".
![Config vars button]( - Input
PORT
and8000
as one config var and click add. - Click "Add buildpack".
- Add "python" and "nodejs" from the list or search if necessary, remember to click save.
- Python must be the first buildpack. They can be dragged into the correct position if needed.
- Click "Reveal Config Vars".
- Select "Deploy" from the tabs.
- Select "GitHub - Connect to GitHub" from deployment methods.
- Click "Connect to GitHub" in the created section.
- Search for the GitHub repository by name.
- Click to connect to the relevant repo.
- Either click
Enable Automatic Deploys
for automatic deploys orDeploy Branch
to deploy manually. Manually deployed branches will need re-deploying each time the repo is updated. Automatic will build the app each time you use you add, commit and push new code. - Click
View
to view the deployed site.
The site is now live and operational
- The terminal function and template for the deployable application was provided by Code Institute, with special mention to Matt Rudge
-
Thank you to Ed Barron. He's an incredible engineer who helped with a lot of syntax based issues I was having, particularly with reading/writing to
lists.json
I feel very lucky to know him and be able to pick his brain. He's helped me no end with understanding the why and how of what I'm writing. -
Thank you to Spencer Barriball He's been an amazing mentor and has put my mind at ease with several course based issues. Before starting this project we brainstormed ideas for what would be achievable, and it really gave me the confidence I needed to just get started with this.
-
As always hank you to Dave Horrocks for providing an incredibly detailed readme template to use, and just in general for being super helpful anytime I've had an issue or question.
-
A special thanks to Maya Claveau for continuously breaking the app during testing, allowing me to squish several bugs I otherwise would not have known existed!