From ac1975315c8f3186967b203e61f72f4da0ade515 Mon Sep 17 00:00:00 2001 From: Andrew Ridgway Date: Tue, 29 Oct 2024 14:36:29 +1000 Subject: [PATCH] initial --- .gitea/workflows/build_push.yml | 53 ++++++++++++ .gitignore | 4 + README.md | 7 ++ base.Dockerfile | 11 +++ change_db.sh | 7 ++ compose_up_cmd.sh | 7 ++ docker-compose.yml | 40 +++++++++ flask.Dockerfile | 14 ++++ pyproject.toml | 3 + requirements.txt | 11 +++ src/flask/add_user.py | 29 +++++++ src/flask/charts/BeerCharts.py | 52 ++++++++++++ src/flask/charts/__init__.py | 0 src/flask/mongo/__init__.py | 0 src/flask/mongo/build_db.py | 76 +++++++++++++++++ src/flask/mongo/get_conn.py | 19 +++++ src/flask/mongo/query_db.py | 55 ++++++++++++ src/flask/mongo/user_db.py | 63 ++++++++++++++ src/flask/static/data_plot.html | 61 ++++++++++++++ src/flask/table/__init__.py | 0 src/flask/table/table_builder.py | 90 ++++++++++++++++++++ src/flask/templates/base.html | 26 ++++++ src/flask/templates/index.html | 37 ++++++++ src/flask/templates/updater.html | 67 +++++++++++++++ src/flask/test.py | 5 ++ src/flask/wine_data.py | 140 +++++++++++++++++++++++++++++++ start_env | 4 + 27 files changed, 881 insertions(+) create mode 100644 .gitea/workflows/build_push.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 base.Dockerfile create mode 100755 change_db.sh create mode 100755 compose_up_cmd.sh create mode 100644 docker-compose.yml create mode 100644 flask.Dockerfile create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 src/flask/add_user.py create mode 100644 src/flask/charts/BeerCharts.py create mode 100644 src/flask/charts/__init__.py create mode 100644 src/flask/mongo/__init__.py create mode 100644 src/flask/mongo/build_db.py create mode 100644 src/flask/mongo/get_conn.py create mode 100644 src/flask/mongo/query_db.py create mode 100644 src/flask/mongo/user_db.py create mode 100644 src/flask/static/data_plot.html create mode 100644 src/flask/table/__init__.py create mode 100644 src/flask/table/table_builder.py create mode 100644 src/flask/templates/base.html create mode 100644 src/flask/templates/index.html create mode 100644 src/flask/templates/updater.html create mode 100644 src/flask/test.py create mode 100644 src/flask/wine_data.py create mode 100755 start_env diff --git a/.gitea/workflows/build_push.yml b/.gitea/workflows/build_push.yml new file mode 100644 index 0000000..3fc4ad1 --- /dev/null +++ b/.gitea/workflows/build_push.yml @@ -0,0 +1,53 @@ +name: Build and Push Image +on: [push] + +jobs: + build: + name: Build and push image + runs-on: ubuntu-latest + container: catthehacker/ubuntu:act-latest + if: gitea.ref == 'refs/heads/master' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Create Kubeconfig + run: | + mkdir $HOME/.kube + echo "${{ secrets.KUBEC_CONFIG_BUILDX }}" > $HOME/.kube/config + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: kubernetes + driver-opts: | + namespace=gitea-runner + qemu.install=true + + - name: Login to Docker Registry + uses: docker/login-action@v3 + with: + registry: git.aridgwayweb.com + username: armistace + password: ${{ secrets.REG_PASSWORD }} + + - name: Build Base Image + uses: docker/build-push-action@v5 + with: + context: . + push: true + file: base.Dockerfile + platforms: linux/amd64,linux/arm64 + tags: | + git.aridgwayweb.com/armistace/beer_base_image:latest + + - name: Build and Push + uses: docker/build-push-action@v5 + with: + context: . + push: true + file: flask.Dockerfile + platforms: linux/amd64,linux/arm64 + tags: | + git.aridgwayweb.com/armistace/beer-data:latest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c770f86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*__pycache__* +.venv* +.env* +mongo_data/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..505bdc4 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# BEER SG data storer + +This container will store SG data for beer runs in Mongo and then use that data to calculate Alchohol Content of each beer + +It's pretty loose and requires the Data Entry operator to know whats happening + +Luck for me... That's me! \ No newline at end of file diff --git a/base.Dockerfile b/base.Dockerfile new file mode 100644 index 0000000..c2b05ff --- /dev/null +++ b/base.Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.10 AS beer_base_image + +WORKDIR /wine_data + +COPY requirements.txt . + +RUN apt-get update -y && apt-get upgrade -y && apt-get install -y libsasl2-dev python-dev-is-python3 libldap2-dev libssl-dev + +RUN pip install --upgrade pip + +RUN pip --default-timeout=1000 install -r requirements.txt diff --git a/change_db.sh b/change_db.sh new file mode 100755 index 0000000..7c3289f --- /dev/null +++ b/change_db.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# This little ditty replaces beer_data with wine_Data +# TODO: Update this to take commands so I can basically create a template project for this +# it's the third time i've used this as a basis for a project its becoming habit lol + + +find . \( ! -regex '.*/\..*' \) -type f | xargs sed -i 's/beer_data/wine_data/g' diff --git a/compose_up_cmd.sh b/compose_up_cmd.sh new file mode 100755 index 0000000..dd1fb58 --- /dev/null +++ b/compose_up_cmd.sh @@ -0,0 +1,7 @@ + +docker-compose rm -f +docker system prune -f +docker volume prune -f +docker build -t beer_base_image -f base.Dockerfile . +docker-compose up --remove-orphans --build -d +docker logs -f wine_data_web diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..60a584a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +# Use root/example as user/password credentials +version: '3.1' + +services: + wine_data_web: + container_name: wine_data_web + build: + context: . + dockerfile: flask.Dockerfile + # volumes: + #- ./src/flask:/pool_data/src/flask + ports: + - "80:80" + - "5000:5000" + restart: "unless-stopped" + environment: + MONGO_HOST: mongo + MONGO_USER: root + MONGO_PASS: example + + mongo: + image: mongo + restart: always + ports: + - 27017:27017 + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: example + volumes: + - ./mongo_data:/data/db + + mongo-express: + image: mongo-express + restart: always + ports: + - 8081:8081 + environment: + ME_CONFIG_MONGODB_ADMINUSERNAME: root + ME_CONFIG_MONGODB_ADMINPASSWORD: example + ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ diff --git a/flask.Dockerfile b/flask.Dockerfile new file mode 100644 index 0000000..47206da --- /dev/null +++ b/flask.Dockerfile @@ -0,0 +1,14 @@ +FROM git.aridgwayweb.com/armistace/beer_base_image AS flask +#FROM beer_base_image AS flask + +COPY requirements.txt . + +ADD src /wine_data/src + +ENV FLASK_ENV production +ENV FLASK_DEBUG 1 + + +ENTRYPOINT ["flask", "--app", "/wine_data/src/flask/wine_data", "run", "--host=0.0.0.0"] + +#ENTRYPOINT ["python", "/pool_data/src/flask/pool_data.py"] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a578942 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[tool.pyright] +venvPath = "." +venv = ".venv" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ef76f0b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,11 @@ +pymongo[srv] +flask +requests_html +beautifulsoup4 +click +Flask-WTF +bootstrap-flask +waitress +bokeh +pandas +duckdb \ No newline at end of file diff --git a/src/flask/add_user.py b/src/flask/add_user.py new file mode 100644 index 0000000..d03f7d2 --- /dev/null +++ b/src/flask/add_user.py @@ -0,0 +1,29 @@ +import os +import click + +import mongo.user_db as user_db + +@click.command() +@click.option('--username', type=str, help="Username to be added or updated") +@click.option('--password', type=str, help="Password to be added or updated") + +def main(username, password): + """ + little cli program to update the + user table in mongo + this rightly should eventually be + and admin tool but right now this will dow + """ + user_collection = user_db.user_data() + new_record = { + "username" : f"{username}", + "password" : f"{password}" + } + if user_collection.user_exists(new_record["username"]): + user_collection.update_user(user_collection.existing_record["_id"], new_record["password"]) + else: + user_collection.add_user(new_record["username"], new_record["password"]) + + +if __name__ == "__main__": + main() diff --git a/src/flask/charts/BeerCharts.py b/src/flask/charts/BeerCharts.py new file mode 100644 index 0000000..3655e22 --- /dev/null +++ b/src/flask/charts/BeerCharts.py @@ -0,0 +1,52 @@ +import sys + +from bokeh.models.widgets import DataCube +from bokeh.plotting import figure + +from mongo.get_conn import db_conn + +class BeerCharts(): + def __init__(self): + self.db = db_conn() + + def bar_chart(self, items, data): + return 0 + + + def line_chart(self, title, field, limit): + data = self.db.beer_db + data = data.find({}).sort("date", -1).limit(limit) + dates = [] + data_list = [] + date_count = {} + for record in data: + if field in record and record[field] != "None": + if record["date"] not in dates: + print("new date record") + dates.append(record["date"]) + data_list.append(float(record[field])) + print (dates) + print (data_list) + else: + if record["date"] in date_count: + date_count[record["date"]] += 1 + else: + date_count[record["date"]] = 2 + print(len(data_list)) + current_data = data_list[len(data_list) - 1] + data_list[len(data_list) - 1] = (float(record[field]) + current_data) / date_count[record["date"]] + + print(dates) + print(data_list) + + p = figure(x_range=dates, height=250, title=title, + toolbar_location=None, tools="") + + p.line(x=dates, y=data_list) + + p.xgrid.grid_line_color = None + if not data_list: + p.y_range.start = 0 + else: + p.y_range.start = round(min(data_list) - 1) + return p diff --git a/src/flask/charts/__init__.py b/src/flask/charts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/flask/mongo/__init__.py b/src/flask/mongo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/flask/mongo/build_db.py b/src/flask/mongo/build_db.py new file mode 100644 index 0000000..2076f34 --- /dev/null +++ b/src/flask/mongo/build_db.py @@ -0,0 +1,76 @@ +import string +import secrets + +from mongo.get_conn import db_conn + +class wine_data: + """ + This class will allow us to + interact with our data to interact + just create a pool_data var + """ + def __init__(self): + #db_conn has all the the things + #already created from here + #we can get self.db.real_db etc + self.db = db_conn() + + def record_exists(self, date, beer_run_id): + """ + This function will accept an address + if it find that address in the database it will return True + and set set the existing_record variable of the class to the + queried record + """ + query = { "date" : f"{date}", "beer_run_id": f"{beer_run_id}"} + record = self.db.beer_db.find_one(query) + if record: + self.existing_record = record + return True + else: + return False + + + def create_re_record(self, beer_run_id, beer_type, sg, date, final_reading=False, comment=""): + """ + create_re_record creates a whole new record + takes the required 7 inputs + 1. beer_run_id + 2. beer_type + 3. sg + 4. date + 5. comment(optional) + It will autogenerate the id string + this string will be automatically selected + on view in future + """ + key = self.create_id() + insert_record = { + "_id" : f"{key}", + "beer_run_id": f"{beer_run_id}", + "beer_type": f"{beer_type}", + "sg": f"{sg}", + "date": f"{date}", + "final_reading": f"{final_reading}", + "comment": f"{comment}" + + } + self.db.beer_db.insert_one(insert_record) + + def update_re_record(self, id, field, value): + """ + update_re_record + will update the requested field to value for the + selected field + """ + #TODO: do we need to make this take more than 1 id? + + query = { "_id": f"{id}"} + update_val = {"$set": {f"{field}": f"{value}" }} + self.db.beer_db.update_one(query, update_val) + + def create_id(self): + alphabet = string.ascii_letters + string.digits + key = ''.join(secrets.choice(alphabet) for _ in range(24)) + return key + diff --git a/src/flask/mongo/get_conn.py b/src/flask/mongo/get_conn.py new file mode 100644 index 0000000..91a88cb --- /dev/null +++ b/src/flask/mongo/get_conn.py @@ -0,0 +1,19 @@ +from pymongo import MongoClient +import os + +class db_conn: + def __init__(self): + self.db_user = os.getenv('MONGO_USER') + self.db_pass = os.getenv('MONGO_PASS') + self.db_host = os.getenv('MONGO_HOST') + self.client = self.get_client() + self.db = self.client['beer_db'] + self.beer_db = self.db['wine_data'] + self.users = self.db['users'] + self.inspections = self.db['inspections_db'] + + def get_client(self): + CONNECTION_STRING = f"mongodb://{self.db_user}:{self.db_pass}@{self.db_host}/beer_db?authSource=admin" + return MongoClient(CONNECTION_STRING) + + diff --git a/src/flask/mongo/query_db.py b/src/flask/mongo/query_db.py new file mode 100644 index 0000000..7537894 --- /dev/null +++ b/src/flask/mongo/query_db.py @@ -0,0 +1,55 @@ +import string +import secrets + +from mongo.get_conn import db_conn + +class pool_query: + """ + This class will allow us to + interact with our data to interact + just create a realestate_data var + """ + def __init__(self): + #db_conn has all the the things + #already created from here + #we can get self.db.real_db etc + self.db = db_conn() + + def record_exists(self, beer_run_id, date): + """ + This function will accept an address + if it find that address in the database it will return True + and set set the existing_record variable of the class to the + queried record + """ + query = {"beer_run_id": f"{beer_run_id}", "date": f"{date}"} + record = self.db.beer_db.find_one(query) + if record: + self.existing_record = record + return True + else: + return False + + def get_top(self, num_limit, value_field): + """ + This function will return the + last n records of the chosen value field + It will take the number of records you want to + return as a parameter + """ + records = self.db.beer_db.find({}, {"beer_run_id": 1, "_id": 0, "date": 1, f"{value_field}": 1}).sort("date", -1).limit(num_limit) + return records + + def user_check(self, username, password): + """ + function to check username and password + back in db + """ + #TODO: this ueses my own quick hack it likley needs to be rewrittent to follow best practice + + query = { "username" : f"{username}", "password" : f"{password}" } + record = self.db.users.find_one(query) + if record: + return True + else: + return False diff --git a/src/flask/mongo/user_db.py b/src/flask/mongo/user_db.py new file mode 100644 index 0000000..8e25970 --- /dev/null +++ b/src/flask/mongo/user_db.py @@ -0,0 +1,63 @@ +import string +import secrets + +from mongo.get_conn import db_conn + + +class user_data: + """ + This class will allow us to + interact with our data to interact + just create a user_data var + """ + def __init__(self): + self.db = db_conn() + + def create_id(self): + alphabet = string.ascii_letters + string.digits + key = ''.join(secrets.choice(alphabet) for _ in range(24)) + return key + + def user_exists(self, username): + """ + This function will accept a username + if it find that user in the database it will return True + and set set the existing_record variable of the class to the + queried record + """ + query = { "username" : f"{username}" } + record = self.db.users.find_one(query) + if record: + self.existing_record = record + return True + else: + return False + + + + def add_user(self, username, password): + """ + add to user table + function accepts the username and password + it will generate a uniqe key + """ + + key = self.create_id() + insert_record = { + "_id" : f"{key}", + "username" : f"{username}", + "password" : f"{password}" + } + self.db.users.insert_one(insert_record) + + def update_user(self, id, password): + """ + update the user record password + requires the id to be updated + """ + + query = { "_id": f"{id}"} + update_val = {"$set": {"password": f"{password}" }} + self.db.users.update_one(query, update_val) + + diff --git a/src/flask/static/data_plot.html b/src/flask/static/data_plot.html new file mode 100644 index 0000000..d5d1fd7 --- /dev/null +++ b/src/flask/static/data_plot.html @@ -0,0 +1,61 @@ + + + + + Bokeh Plot + + + + + +
+ + + + + \ No newline at end of file diff --git a/src/flask/table/__init__.py b/src/flask/table/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/flask/table/table_builder.py b/src/flask/table/table_builder.py new file mode 100644 index 0000000..3a9ae53 --- /dev/null +++ b/src/flask/table/table_builder.py @@ -0,0 +1,90 @@ +import sys + +from mongo.get_conn import db_conn +import pandas as pd +import duckdb + +class TableBuilder(): + def __init__(self) -> None: + self.db = db_conn() + data = self.db.beer_db + data = data.find({}).sort("date", -1) + df_dict = {} + df_dict["beer_run_id"]=[] + df_dict["sg"] = [] + df_dict["date"] = [] + df_dict["final_reading"] = [] + + for record in data: + df_dict["beer_run_id"].append(record["beer_run_id"]) + df_dict["sg"].append(record["sg"]) + df_dict["date"].append(record["date"]) + df_dict["final_reading"].append(record["final_reading"]) + + self.df_dict = df_dict + self.df = pd.DataFrame(data=self.df_dict) + + def done_runs_build(self, limit=10) -> pd.DataFrame: + + df = self.df + sql = f""" + SELECT x.beer_run_id as beer_run_id, + max(sg) as max, + min(sg) as min, + y.date as final_reading_date + FROM df x + JOIN + ( SELECT DISTINCT beer_run_id, date + FROM df + WHERE final_reading = 'True' + ) y ON x.beer_run_id = y.beer_run_id + GROUP BY x.beer_run_id, y.date + ORDER BY x.beer_run_id desc + LIMIT {limit} + """ + df_sum = duckdb.sql(sql).df() + sql = f""" + SELECT x.beer_run_id as "Beer Run", + x.max as "Max", + x.min as "Min", + ROUND(((CAST (max AS INTEGER) - CAST(min AS INTEGER)) / 7.36) + 0.5, 2) AS "Alcohol Prediction +/- 0.5", + cast(final_reading_date as DATE) + INTERVAL 14 DAY as "Ready Date" + + FROM df_sum x + """ + df_calc = duckdb.sql(sql).df() + return df_calc + + def current_runs_build(self, limit=10) -> pd.DataFrame: + df = self.df + sql = f""" + SELECT x.beer_run_id as beer_run_id, + max(sg) as max, + min(sg) as min, + min(cast(x.date as DATE)) as first_reading_date + FROM df x + LEFT JOIN + ( SELECT DISTINCT beer_run_id + FROM df + WHERE final_reading = 'True' + ) y ON x.beer_run_id = y.beer_run_id + WHERE y.beer_run_id is null + GROUP BY x.beer_run_id + ORDER BY x.beer_run_id desc + LIMIT {limit} + """ + df_sum = duckdb.sql(sql).df() + sql = f""" + SELECT x.beer_run_id as "Beer Run", + x.max as "Max", + x.min as "Min", + ROUND(((CAST (max AS INTEGER) - 1012) / 7.36) + 0.5, 2) AS "Alcohol Prediction (1012) +/- 0.5", + first_reading_date + INTERVAL 7 DAY as "Earliest Bottling/Kegging Date" + + FROM df_sum x + """ + df_calc = duckdb.sql(sql).df() + return df_calc + + + diff --git a/src/flask/templates/base.html b/src/flask/templates/base.html new file mode 100644 index 0000000..f619e1c --- /dev/null +++ b/src/flask/templates/base.html @@ -0,0 +1,26 @@ + + + + + + + {% block title %} Let there Be Pool Data {% endblock %} + + {{ bootstrap.load_css() }} + + + + + + + {% block content %} {% endblock %} + + + {{ bootstrap.load_js() }} + + diff --git a/src/flask/templates/index.html b/src/flask/templates/index.html new file mode 100644 index 0000000..244597f --- /dev/null +++ b/src/flask/templates/index.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} +{% from 'bootstrap5/form.html' import render_form %} + +{% block title %} +Login to Pool Data Tracker +{% endblock %} +{% block content %} + + + +
+ {% if try_again %} +

Login Failed Please try Again

+ {% endif %} + +
+
+
+ +

WHOOOOOOO ARE YOU!

+ +

If you know you know

+ + {{ render_form(form) }} + +

{{ message }}

+ +
+
+
+
+ +{% endblock %} diff --git a/src/flask/templates/updater.html b/src/flask/templates/updater.html new file mode 100644 index 0000000..6d79b1d --- /dev/null +++ b/src/flask/templates/updater.html @@ -0,0 +1,67 @@ +{% extends 'base.html' %} +{% from 'bootstrap5/form.html' import render_form %} + +{% block title %} + Data Input +{% endblock %} +{% block content %} + + +
+
+
+ +

Input Data you want to store

+ {% if success %} +

Thank you {{ updater_name | safe }}, Data Updated Successfully

+ {% endif %} + +
+
+ + + + + + +
+ {{ render_form(form) }} +
+
+
+ +

Current Runs

+ {{ current_data | safe }} + +

Previous Runs

+ {{ wine_data | safe }} + +
+
+
+
+
+{% endblock %} diff --git a/src/flask/test.py b/src/flask/test.py new file mode 100644 index 0000000..8a4794c --- /dev/null +++ b/src/flask/test.py @@ -0,0 +1,5 @@ +import table.table_builder as table_builder + +test = table_builder.TableBuilder() + +print(test.table_build()) diff --git a/src/flask/wine_data.py b/src/flask/wine_data.py new file mode 100644 index 0000000..4602320 --- /dev/null +++ b/src/flask/wine_data.py @@ -0,0 +1,140 @@ +from bokeh.core.enums import SpatialUnitsType +import mongo.build_db as wine_database +import mongo.query_db as wine_database_query +from table import table_builder + +from flask import Flask, render_template, request, jsonify, redirect, session +from flask_wtf import FlaskForm, CSRFProtect +from flask_bootstrap import Bootstrap5 +from wtforms import StringField, SubmitField, DateField, IntegerField, PasswordField, DecimalField, RadioField, TextAreaField, BooleanField +from wtforms.validators import DataRequired, Length, Optional +from waitress import serve +from bokeh.models.layouts import HBox +from bokeh.plotting import column +from charts import BeerCharts +from bokeh.io import output_file, show +from bokeh.layouts import row + + +app = Flask(__name__) +app.secret_key = 'testsecret' #this value will change + +bootstrap = Bootstrap5(app) + +csrf = CSRFProtect(app) +# used to configure the bokeh plot for graphs +output_file("/wine_data/src/flask/static/data_plot.html") + +def create_graphs(): + chart = BeerCharts.BeerCharts() + sg = chart.line_chart("SG", "sg", 30) + show(column(sg)) + +def data_frame_to_table(df) -> str: + + tr_replace_string = '' + return_html = df.to_html(col_space='75px', index=False, + justify='center', border=3).replace('', tr_replace_string) + return return_html + +class userForm(FlaskForm): + username = StringField("User Name?", validators=[DataRequired()]) + password = PasswordField("Password?") + submit = SubmitField("Letsa GO!") + +class dataForm(FlaskForm): + beer_run_id = IntegerField("Beer Run ID") + beer_run_type = TextAreaField("Beer Type") + Date = DateField("Date:") + sg = IntegerField("SG Reading") + final_run = BooleanField("Final Reading?") + comment = TextAreaField("Any Comments?", validators=[Optional()]) + submit = SubmitField("Write it, Write it REAAAAAAL GOOOD") + +@app.route("/", methods=["GET","POST"]) +def index(): + form = userForm() + if form.validate_on_submit(): + username = form.username.data + password = form.password.data + db = wine_database_query.pool_query() + if db.user_check(username, password): + session['logged_in'] = True + return redirect("/updater") + else: + return render_template("index.html", try_again=True, form=form) + else: + return render_template("index.html", try_again=False, form=form) + +@app.route("/updater", methods=["GET", "POST"]) +def updater(): + if 'logged_in' not in session: + return redirect("/") + table_Data = table_builder.TableBuilder() + predicted_alc_table = table_Data.done_runs_build() + current_runs_table = table_Data.current_runs_build() + + beer_html = data_frame_to_table(predicted_alc_table) + current_html = data_frame_to_table(current_runs_table) + + query_db = wine_database_query.pool_query() + query = query_db.get_top(10, "sg") + form = dataForm() + + + + if form.validate_on_submit(): + database = wine_database.wine_data() + new_record = { + "date": f'{form.Date.data}', + "beer_run_id": f'{form.beer_run_id.data}', + "beer_type": f'{form.beer_run_type.data}', + "sg" : f'{form.sg.data}', + "final_reading" : F'{form.final_run.data}', + "comment": f'{form.comment.data}' + } + if database.record_exists(new_record["date"], new_record["beer_run_id"]): + for field in database.existing_record: + for new_field in new_record: + if field == new_field: + if database.existing_record[field] != new_record[field]: + database.update_re_record(database.existing_record["_id"], field, new_record[field]) + else: + if new_record["final_reading"] == "True": + final_run_value = True + else: + final_run_value = False + database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], + new_record["date"], final_run_value, new_record["comment"]) + + return render_template("updater.html", wine_data = beer_html, current_data = current_html + , list=query, form=form, success=True, updater_name = "Saucy Beer Maker") + else: + return render_template("updater.html", wine_data = beer_html, current_data = current_html + , list=query, form=form, sucess=False) + +# @app.route("/update_db", methods=["POST"]) +# def wine_data_update(): +# database = wine_database.wine_data() +# new_record = request.json +# if database.record_exists(new_record["date"], new_record["test_user"]): +# for field in database.existing_record: +# for new_field in new_record: +# if field == new_field: +# if database.existing_record[field] != new_record[field]: +# database.update_re_record(database.existing_record["_id"], field, new_record[field]) +# else: +# database.create_re_record(new_record["beer_run_id"], new_record["beer_type"], new_record["sg"], +# new_record["date"], new_record["comment"]) + + + +# @app.route("/pool_top//") +# def user_detail(id): +# query_db = wine_database_query.pool_query() +# query = query_db.get_top(return_number, field) +# return jsonify([row.to_json() for row in query]) + +if __name__ == '__main__': + #app.run(host='0.0.0.0') + serve(app, host='0.0.0.0', port=5000, url_scheme='https') diff --git a/start_env b/start_env new file mode 100755 index 0000000..142b3a6 --- /dev/null +++ b/start_env @@ -0,0 +1,4 @@ +#!/bin/bash + +source .venv/bin/activate +source .env