dylanleigh / PriceAndNutritionTrackingSystem

PANTS is a self-hosted, open-source nutrition tracker and tool for nutritional data analysis of ingredients and recipes.
Apache License 2.0
116 stars 26 forks source link

Future front end developments #6

Closed AustinGrey closed 4 years ago

AustinGrey commented 4 years ago

I recently became interested in building a nutrition tracing app of my own some time ago, but when I saw your project and how it had already overcome some major design hurdles I figured it might be best to lend my support to an existing project. I have experience with both django and web application development (in php, pure html/js, and vue). I was wondering what your plans for a front end are? I notice on the README it states:

Also, the django template frontend is quite basic. It is not really intended for end-user use, only for personal or debugging purposes. It does not have any forms so all data entry including diary is done via the admin interface. Ideally "customer" users should access the service through an app or a single page frontend. Future frontend work will mostly therefore be via other projects using an API (I do plan to add an Android app for my personal use).

I've looked through the code and don't see any API implemented as of yet, and it sounds as though you may not be interested in having an integrated front end developed. How can I contribute to this area? I would love to explore an improved front end but it would need to be integrated if there is no API.

Alternatively I could put together an API design document for your review? I've just completed a 4 month long course on web design and RESTful API's was one of the components. If you approve such a design document I could go ahead and write tests for such an API, and then an implementation as a separate Django app.

AustinGrey commented 4 years ago

As an example, I threw together an API design document for a RESTful API on Ingredients. The file is available in a branch on my fork, here.

The file is an OpenAPI spec document, and should be compatible with any OpenAPI editor. I created it using Stoplight, which is freely available online. You could load up this file into any OpenAPI viewer or documentation generator to get an easily viewable API. A quick search brought up this page, where you could paste the link to the raw spec file (https://raw.githubusercontent.com/AustinGrey/PriceAndNutritionTrackingSystem/3-ingredients-api/reference/PANTS-API.v1.yaml) and begin viewing it in an interactive format. This probably isn't the best viewer out there, but just what came up.

dylanleigh commented 4 years ago

Thanks for the work you've put into the API/Frontend.

My plan is to use Django REST Framework to add the API - there was a little experimental code at /ingredients/filter/ , testing an endpoint that could filter ingredients by various properties, like having calories above or below a certain amount.

The README is a bit outdated/misleading - I'm happy to continue to tweak the Django template frontend further, but ultimately it's probably more practical to focus on an API that can be used for dedicated frontend clients that can provide a richer interface.

I haven't been prioritizing the API because I wasn't ready to start working on any such clients myself, but if you are interested in doing so I can create the serializers using DRF easily. I'll start with the Diary (as this is already per-user, and gets the most frequent changes anyway).

The Ingredient API looks good but the DB schema should be updated first to to allow per-user Ingredient/Recipe objects to be created and edited - adding the user Foreign Key can be done pretty easily but the views will have to be set up to present both the global and per-user items. I'll try and get that done soon as well.

dylanleigh commented 4 years ago

Commit 56baff29823368e621c0ddb3b37954f9fc491085 has added an API for diary - if logged in http://127.0.0.1:8000/api/1/diaryfood/ should be browsable HTML and http://127.0.0.1:8000/api/1/diaryfood/?format=json should give the raw JSON.

AustinGrey commented 4 years ago

Okay I took a stab at using the API to create some prototype front ends. There is now an 'Ingredient Manager' (branch 4-frontend-prototype, commit AustinGrey@59b5df66b94ccdd8c434971403eef1737261236a) prototype that allows basic CRUD for ingredients. It raised a few questions:

  1. Authentication: right now I'm using hard coded basic auth, passing in a user name and password with each request. While this is secure if the server is hosted locally or over https, it is not if hosted over http. What Authentication scheme were you envisioning?
  2. CORS: on your branch the API is only accessible from the same host/port. If I run the server at 127.0.0.1:8000, and my frontend on 127.0.0.1:8001, then requests are blocked because CORS is not set. My branch installs a CORS package for django, and then sets CORS headers on all /api/* endpoints - I don't see a way around this if the api is meant to enable separate front ends.
  3. Searching/Sorting: right now the only filtering options are exact match by object key (e.g. name=salt, name=sa, and name=sal return nothing, but name=Salt returns the Salt ingredient). I added options for partial matches under search key (eg. search=sa returns the Salt ingredient), and sorting on all columns by default
  4. Right now the API errors when attempting to create or update an ingredient with tags, because there's no method to set the tags, only to read them. I know the API is not done so I only mention this if you choose to try out the prototype.
  5. Project Structure: Does it seem worthwhile to you to keep this front end project together with PANTS, and have me submit PR's when work is in a stable state? or would you prefer that the front end is a separate project, no PR's and only a mention to your code?

    Prototype in Firefox: image

dylanleigh commented 4 years ago

Nice work on the prototype frontend - paging through and changing ingredients it's noticeably faster than the Django admin for me.

1) I hadn't thought about the auth much, just assuming the built in session authentication via the 'api-auth' point (or the other login forms) for now. There will need to be more flexible authentication added for things like native clients.

2) I hadn't thought about CORS either - the API will definitely need the headers to allow access. I'll merge the relevant parts from commit 3ae2d5125af510e8afa54e9f99b92bf784d3ec6f

3) My plan is to use django-filter for searching/filtering - this should also allow clients to search across multiple criteria, like "tagged with 'grain' and more than 10% fibre" and similar more complex queries.

4) I'll get the tags on the API soon so this can be tested properly.

5) Either way is fine by me, whichever you're most comfortable with. I'm often unwell and away for days or weeks, so keeping the projects separate would prevent that from holding up PRs or other development.

AustinGrey commented 4 years ago

Thank you for the clarifications. My apologies for my slow response - I was finishing up my undergrad this week.

  1. Understood, the prototype is throwaway code so I will continue to use basic auth for now until I can understand how to log in from a separate front end.
  2. I'll separate out my code for you and make a PR.
  3. I'm a fan of combining efforts until there is a clear need to separate. I'll keep up with working in this project and making PRs.