A normal CRUD app without the "U" + a chart feature
- flask-sqlalchemy - A library for easy ORM
- python-dotenv - For easily tracking environment variables in
.envfiles - gunicorn - Server for heroku
- psycopg2-binary - PostgreSQL driver
Run the python virtual machine to isolate dependency installations. This will also automatically detect and install dependencies in Pipfile
$ pipenv shell
Run flask to start a development server. By default, the site would be served in http://localhost:5000
$ flask run
To test "production" server used in Heroku, start gunicorn instead
$ gunicorn app:app
Default login credentials:
- Username:
admin - Password:
admin
Note: I didn't have enough time to create UI for user signup, but new users may be added through the API (See section on API endpoints and Postman), or directly in the databse
-
Database: Heroku PostgreSQL
Credentials are available in the
.envfile I uploaded in the Google Drive shared folder -
Postman This is helpful for easier access to the API endpoints. The following files are available in
\postman:- API Collection Import:
api.postman_collection.json
- Environment Imports:
local.postman_environment.jsonheroku.postman_environment.json
- API Collection Import:
There are two parts to this (...and really most) implementation (s): front-end (Jinja, HTML, JS, CSS) and back-end (Python). The front-end is what you see from the browser; and for the back-end, I've made several API Endpoints available.
- User:
/api/login/api/logout/api/user/add
- Checkins:
/api/checkin/add/api/checkin/delete/api/delete/table
- Tags:
/api/tags/search
These may be accessible through Postman for easier testing/viewing. Available parameters are also included in the import/export file. Refer to Local Access section
Implementation Notes:
tagsare a separate entity/table for scalability.
Implementation Notes: I also contemplated of whether to design this with API's or to do backend processes directly since they're both on a single server anyway. I went with API's because it was easier to test. It took a little more time setting up, but I think it's worth it
These are available in \templates. Everything else is pretty straightforward
Pages:
- Login Page
- Loading Page
- Table/Chart Page
- (Extra) Hello World Page
Features:
-
Login/Logout
Uses Flask Session to store logged in user data
Implementation Note: I'm known to always go the extra step but for this module, I'm so sorry to say that passwords aren't encrypted. I WAS going to add this later on, but given that I'm already late in submitting this, I no longer had enough time. If I were to add password encryption, I'd just use a basic one way encryption algorithm such as MD5 or SHA in the python code before processing to database.
-
Filter by Date Range
This is my solution to this requirement:
2. Show all check ins, grouped by day
Implementation Note: This is unfortunately all I managed to do, but the filter function is implemented dynamically so it would be simpler to add other filter functions
Implementation Note: Both the table and chart gets updated when filtered. Any operation on the table data will be reflected on the chart/s as well
-
Add/Delete Checkin
Each checkin has a
statusattribute with valuesactiveordeleted. TheDeleteoperation does not actually delete the data, but marks it asdeleted -
Pie Chart
This is a D3 Pie chart. The data available (filtered/unfiltered) is grouped by tags. It's interactable (SVG) and has some basic transitions when filtering the data.
Implementation Note: There's a bug in the transition when only one tag remains. This is fixable but I didn't have enough time
Implementation Note:
SVGis easiest to implement when it comes to interactable charts but when dealing with bigger datasets, acanvasimplementation would be better suited.
-
For the front-end, I didn't spend too much time on error and asynchronous handling, but at the bare minimum, they do exist for both add/delete operations
-
On local, I sometimes get a database connection error. I put out an
alertto refresh page when this happens. On the flipside, you get to really appreciate the loading screen when this error occurs since the page doesn't go further anymore. -
I'll disclose this just in case my python code isnt optimal, this is the first time I'm using Python that isn't a personal project. Took a risk here, but I hope it's not too shoddy
├── postman # Contains postman import files
├── src
| ├── api
| | ├── checkin.py # Contains available /api/checkin routes
| | ├── tags.py # Contains available /api/tags routes
| | └── user.py # Contains available /api/user routes
| |
| └── models # ORM files (flask-sqlalchemy)
| ├── checkin.py
| ├── tag.py
| └── user.py
|
|
├── static # Directory for assets such as scripts and images
| ├── css # Contains stylesheets per pages
| └── js # Contains scripts per module
|
├── templates # Jinja templates
| ├── components # Reusable component templates
| └── pages # Page templates
|
├── .env
├── .env-sample
|
├── app.py # Main/start python code
├── routes.py # Contains available browser routes.
|
├── README.pdf
└── README.md
- Google Drive Shared Folder - https://drive.google.com/drive/u/1/folders/1Ye28ZJQKigaFUhn0G5QcBu2LyAr7M65I
- Github Repository - https://github.com/kayecandy/tm-time-tracker
- Live Demo (Heroku) - https://tm-time-tracker.herokuapp.com/