Giter Site home page Giter Site logo

nikitadanilenko / foodie Goto Github PK

View Code? Open in Web Editor NEW
0.0 3.0 2.0 5.37 MB

Food statistics calculator based on the Canadian Nutrient File

Home Page: https://danilenko.io/foodie/#/login

License: BSD 3-Clause "New" or "Revised" License

Scala 43.28% Dockerfile 0.01% HTML 0.06% Elm 55.63% JavaScript 0.13% CSS 0.87% Shell 0.02%
database elm-lang hacktoberfest nutrients-calculator postgresql property-testing scala

foodie's Introduction

Caveats

  1. There are no values for iodine in the database.
  2. Several values may be incomplete. For instance, biotin is only listed for a handful of foods.

Database

  1. Create a database, a corresponding user, and connect the two:
    > psql -U postgres
    psql> create database <foodie>;
    psql> create user <foodie> with encrypted password <password>;
    psql> grant all privileges on database <foodie> to <foodie>;
    psql> grant pg_read_server_files to "<foodie>";
    
    The last command is important for the population of the actual CNF database. When psql is running in Docker it may also be necessary to add
    psql>\c <foodie>
    foodie>grant all privileges on all tables in schema public to <foodie>;
    
    Additionally, at least one migration may require super-user access for the user, unless the extension uuid-ossp is already defined.
  2. Populate the CNF database by once running the script under scripts/populate_cnf_db.sql. To achieve that run the following steps:
    1. Open a console in the project folder
    2. > psql -U postgres
    3. It may be necessary to switch to the project folder in psql as well. This can be achieved with psql> \cd <absolute path>;.
    4. psql> \ir scripts/populate_cnf_db.sql
    5. In case of Docker:
      1. The script files are copied to /tmp/scripts via docker-compose.yml.
      2. Connect to container docker exec -it postgres /bin/bash.
      3. Change into tmp via cd /tmp.
      4. Run psql -U <foodie-user> -d <foodie-database> -h db, enter the password.
      5. Run the script exactly as above.
    6. Why not a migration? There are several reasons for that:
      1. To copy from via SQL the user needs to be a superuser, which may be problematic.
      2. copy from does not handle relative paths, i.e. one needs an absolute path. Absolute paths present an unnecessary constraint and impede development, and deployment.
      3. In theory one may use a different population set or no population at all. Both work fine with an external population, but not with a migration.
  3. The system scans for migrations in the folder conf/db/migrations/default and applies new ones. After a migration one should re-generate database related code:
    1. sbt slickGenerate generates the base queries, and types.

Minimal Docker database backup strategy

Depending on the setup the commands below may need to be prefixed with sudo.

  1. Start containers detached docker compose up -d
  2. Connect to the container docker compose run db bash
  3. Dump the database as insert statements (for better debugging): pg_dump -h <container-name> -d <database-name> -U <user-name> --inserts -W > /tmp/<backup-file-name>.sql. You will be prompted for the password for said user. Moving the file to /tmp handles possible access issues. Even better - dump only the relevant tables by listing them with -t <table_name> for each table (prefixed with public.).
    pg_dump -h foodie-postgres -d foodie -t public.user -t public.session -t public.meal_entry -t public.meal -t public.complex_food -t public.recipe -t public.complex_ingredient -t public.recipe_ingredient -t public.reference_entry -t public.reference_map  -U foodie --insert -W > /tmp/<date>.sql
    
  4. Find the id the desired container: docker ps
  5. In a third CLI copy the backup file to your local file system: docker cp <container-id>:/tmp/<backup-file-name>.sql <path-on-local-file-system>

Deployment

For the moment the deployment is handled manually. There needs to be a running Docker service running on the target machine.

  1. Connect to the target machine.
  2. If this is the first deployment, clone Git project into a folder of your choosing.
  3. Change into the local Git repository of the project.
  4. Run git pull. It is possible that there will be a conflict with the db.env, if the development password has changed.
  5. Make sure that db.env contains deployment values.
  6. If this is the first deployment, create a file deployment.env containing all necessary environment variables (cf. application.conf).
  7. Make sure that all necessary environment variables are set in deployment.env, and these variables contain the desired deployment values. As a reference, one can use the .env file - every key present in the .env file needs to be set in the deployment.env as well. Caveat: Avoid # symbols, because these can behave differently between dotenv and Docker.
  8. Run docker compose up (possibly with sudo). If you want to deploy a specific version, update the image from latest to the desired tag in the docker-compose.yml.
  9. If this is the first deployment, connect to a bash in the Docker db container, and perform the database setup steps described above.
  10. If this is the first deployment, restart the service (only the back end is sufficient). There is a tricky optimisation in the code: Some of the CNF tables are kept in memory to avoid queries (particularly in the case of statistics). However, the tables are loaded only once at the start of the service. Since the CNF database is initially empty, so are the memory values.

CI

Run tests Build and publish back end Build and publish back end

foodie's People

Contributors

anjanka avatar dependabot[bot] avatar nikitadanilenko avatar scala-steward avatar

Watchers

 avatar  avatar  avatar

foodie's Issues

Add tests for user service

There should be property tests for the user service functions. In particular, the session id handling strategy should be tested.

Replace direct references to Live companions

Currently there is a couple of direct references to Live implementations between services. Such references break the DI pattern. Replace them with proper DI. It may be necessary to adjust the entire service/companion structure to avoid overloading.

Add auto-scale feature for recipes

When creating a recipe with a serving size based on weights, it is sensible to adjust the number of servings to the overall weight, divided by the serving size. This step should be automated, to avoid manual adjustments.

Add duplication feature

Parent objects and their respective children should provide a duplication function.

  • recipes
  • meals
  • reference maps

The naming can be kept simple by adding (copy) or similar as suffix.

Differentiate "missing" and "proper zero"

The notes for the CNF database explicitly state that a missing value is different from a proper zero at that value. The difference is important because many values are missing, and may be mistaken for "lacking in the menu". The difference should be visible in the front end.

Account for yield and refuse

The CNF database contains yield and refuse amounts that are currently ignored. The values denote cooking losses. These amounts should be handled in a sensible way.

Set up variable check

Create a script that checks whether all values in deployment.env are set by matching the keys to those in .env.

Possibly incorporate the script into docker-compose.yml to abort erroneous deployments early.

Apply CSS lint, and improve CSS

Running CSS Lint currently gives a lot of warnings, and some errors. Most warnings can be ignored, since they refer to an outdated standard (don't use identifier in selection), and the errors are not errors, but in fact valid, and semantically correct.

Task: Rearrange CSS for better legibility, apply best practices for CSS

Add validation for registration token

Upon entering the page for the confirmation of the registration, the token should be checked via the back end, because a used token will lead to a duplicate key constraint violation (nickname is key).

Alternatively, use a more generic error message.

Provide 'step-in' UX for the creation of new recipes/meals/reference maps

When creating a new parent object (e.g. recipe), the UI should switch directly to the "edit children" view. The tradeoff for this decision is that it is more inconvenient to delete a newly added value. However, the deletion use case is considered to be an edge case, while the proper creation use case benefits from the described changes.

Add tests containing complex ingredients

All statistics currently only account for regular ingredients. Add tests handling complex ingredients as well. At least tests with one layer references should be added.

Add navigation to recipes, and ingredients

From the meal entry editor (resp. the ingredients editor) it may be sensible to have a shortcut link to the recipes (resp. foods) to double-check and quickly edit. This should be a simple link without further interactions.

Add option to change the email address

Consider security:

  • Is it sufficient to be logged in?
  • Confirm via password?
  • Use existing email address and new one?
  • What to do in case the email access is lost?

Switch to `.env` files

  • Use dotenv plugin
  • Move all default values into .env file
  • Update Readme.md: The deployment.env can be created from .env

Allow multiple identities to track consumption for more than one person

One may want to employ the foodie application for multiple people in the same household, i.e. people whose recipe lists coincide. At the state of June 2023 such a requirement can be implemented only by having separate accounts. Separate accounts do not have the option to share recipes, and sharing recipes has non-trivial consequences - for instance, person A could share, and later modify or even delete a recipe with person B. To avoid data loss, some adjustment would have to be necessary on the end of person B, either automatically or manually.

Having multiple identities within the same account provides a pragmatic compromise. One has consistent sharing of recipes, without possibly problematic dependencies.

Add statistics about last use of recipe

There should be a statistics area that displays all recipes with the last date the recipe was used (and likely the meal name).

Why in statistics? Because the computation is costly, and is passive, hence it does not fit into the recipe editor.

Handle capitalization in CNF database

At least the relevant values in the NUTRIENT NAME.csv file are all capitalized. It is more sensible to use a more textual representation. However, some abbreviations (e.g. DHA) should remain as they are.

Normed complex ingredients

Allow to use only normed quantities of complex ingredients, i.e. 100g and 100ml. The benefit is a more user-friendly experience while adding complex ingredients.

The decision which unit to choose is only possible when both units are available. Caveat: Keep in mind that all existing entries should be properly migrated, because they may refer to non-standard quantities.

Side note: Alternatively, one could perform the computation on the front end side only. However, this would somewhat break the "all logic in the back end" decision.

Rethink versioning

In its current state the versioning actually has three different versions: the project, the back end, and the front end. However, the project's version is redundant, and misleading, because it may be very different from both back end and front end. A better approach is to use two distinct versions for back end, and front end, and possibly accomodate the complement version in both, i.e. tags like v1.2.3-2.1.4 which denote how which versions are compatible with which complement version.

The concept seems poorly thought through now - rethink it, as the title suggests!

Streamline deployment

  • .env file should not conflict with deployment.env
  • db.env should be handled similar to deployment.env, because the file should have different contents in deployment

Add DB test for cycle check

The cycle check property test needs to use the database, because the cycle check is implemented in SQL directly. Most of the setup already exists (cf. TODO in code), but the setup needs to be extended to actually insert all necessary entities.

The test should be defined in a new class for better separation of successful test runs.

Make responses conform with REST standard

Several requests give non-standard answers in standard REST scenarios. Adjust these answers.

Note: The front end should not need any changes, because successes and failures are (should be?) recognized correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.