Moved all static files for recipe_api

This commit is contained in:
Jadowyne Ulve 2025-04-26 22:06:20 -05:00
parent 9f4084a4d7
commit 987a665f72
13 changed files with 81 additions and 60 deletions

View File

@ -1,6 +1,12 @@
from application import postsqldb
import config
import psycopg2
import random
import string
def getUUID(n):
random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=n))
return random_string
def getModalSKUs(site, payload, convert=True):
database_config = config.config()
@ -42,6 +48,23 @@ def getItemData(site:str, payload:tuple, convert:bool=True):
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, payload, sql)
def getUnits(convert:bool=True):
database_config = config.config()
recordset = ()
sql = f"SELECT id, fullname FROM units;"
try:
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql)
rows = cur.fetchall()
if rows and convert:
recordset = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows]
if rows and not convert:
recordset = rows
return recordset
except (Exception, psycopg2.DatabaseError) as error:
raise postsqldb.DatabaseError(error, (), sql)
def getRecipes(site:str, payload:tuple, convert=True):
recordset = []
count = 0

View File

@ -1,16 +1,19 @@
from flask import Blueprint, request, render_template, redirect, session, url_for, send_file, jsonify, Response, current_app, send_from_directory
import psycopg2, math, json, datetime, main, copy, requests, process, database, pprint, MyDataclasses
from config import config, sites_config
from main import unfoldCostLayers
# 3rd party imports
from flask import (
Blueprint, request, render_template, session, jsonify, current_app, send_from_directory
)
import math
# application imports
import main
from user_api import login_required
import os
import postsqldb, webpush
import webpush
from application.recipes import database_recipes
from application import postsqldb as db
recipes_api = Blueprint('recipes_api', __name__)
recipes_api = Blueprint('recipes_api', __name__, template_folder="templates", static_folder="static")
@recipes_api.route("/recipes")
@recipes_api.route("/")
@login_required
def recipes():
"""This is the main endpoint to reach the webpage for a list of all recipes
@ -20,11 +23,11 @@ def recipes():
description: returns recipes/index.html with sites, current_site.
"""
sites = [site[1] for site in main.get_sites(session['user']['sites'])]
return render_template("recipes/index.html",
return render_template("index.html",
current_site=session['selected_site'],
sites=sites)
@recipes_api.route("/recipe/<mode>/<id>")
@recipes_api.route("/<mode>/<id>")
@login_required
def recipe(id, mode='view'):
"""This is the main endpoint to reach the webpage for a recipe's view or edit mode.
@ -44,16 +47,15 @@ def recipe(id, mode='view'):
200:
description: Respondes with either the Edit or View webpage for the recipe.
"""
database_config = config()
with psycopg2.connect(**database_config) as conn:
units = postsqldb.UnitsTable.getAll(conn)
units = database_recipes.getUnits()
print("woot")
if mode == "edit":
return render_template("recipes/recipe_edit.html", recipe_id=id, current_site=session['selected_site'], units=units)
return render_template("recipe_edit.html", recipe_id=id, current_site=session['selected_site'], units=units)
if mode == "view":
return render_template("recipes/recipe_view.html", recipe_id=id, current_site=session['selected_site'])
return render_template("recipe_view.html", recipe_id=id, current_site=session['selected_site'])
@recipes_api.route('/recipes/getRecipes', methods=["GET"])
@recipes_api.route('/getRecipes', methods=["GET"])
@login_required
def getRecipes():
""" Get a subquery of recipes from the database by passing a page, limit
@ -73,7 +75,7 @@ def getRecipes():
return jsonify({'recipes': recipes, 'end': math.ceil(count/limit), 'error': False, 'message': 'fetch was successful!'})
return jsonify({'recipes': recipes, 'end': math.ceil(count/limit), 'error': True, 'message': f'method is not allowed: {request.method}'})
@recipes_api.route('/recipe/getRecipe', methods=["GET"])
@recipes_api.route('/getRecipe', methods=["GET"])
@login_required
def getRecipe():
""" Get a query for recipe id from database by passing an id
@ -91,7 +93,7 @@ def getRecipe():
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe returned successfully!'})
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed'})
@recipes_api.route('/recipes/addRecipe', methods=["POST"])
@recipes_api.route('/addRecipe', methods=["POST"])
@login_required
def addRecipe():
""" post a new recipe into the database by passing a recipe_name and recipe description
@ -103,10 +105,8 @@ def addRecipe():
if request.method == "POST":
recipe_name = request.get_json()['recipe_name']
recipe_description = request.get_json()['recipe_description']
database_config = config()
site_name = session['selected_site']
user_id = session['user_id']
with psycopg2.connect(**database_config) as conn:
recipe = db.RecipesTable.Payload(
name=recipe_name,
author=user_id,
@ -117,7 +117,7 @@ def addRecipe():
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe added successful!'})
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method}'})
@recipes_api.route('/recipe/getItems', methods=["GET"])
@recipes_api.route('/getItems', methods=["GET"])
@login_required
def getItems():
""" Pass along a page, limit, and search strings to get a pagination of items from the system
@ -138,7 +138,7 @@ def getItems():
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":True, "message":"There was an error with this GET statement"})
@recipes_api.route('/recipe/postUpdate', methods=["POST"])
@recipes_api.route('/postUpdate', methods=["POST"])
@login_required
def postUpdate():
""" This is an endpoint for updating an RecipeTuple in the sites recipes table
@ -159,7 +159,7 @@ def postUpdate():
return jsonify({'recipe': recipe, 'error': False, 'message': 'Update of Recipe successful!'})
return jsonify({'recipe': recipe, 'error': True, 'message': 'Update of Recipe unsuccessful!'})
@recipes_api.route('/recipe/postCustomItem', methods=["POST"])
@recipes_api.route('/postCustomItem', methods=["POST"])
@login_required
def postCustomItem():
""" post a recipe item to the database by passing a uuid, recipe_id, item_type, item_name, uom, qty, and link
@ -173,7 +173,7 @@ def postCustomItem():
site_name = session['selected_site']
rp_id = int(request.get_json()['rp_id'])
recipe_item = db.RecipesTable.ItemPayload(
uuid=f"%{int(request.get_json()['rp_id'])}{database.getUUID(6)}%",
uuid=f"%{int(request.get_json()['rp_id'])}{database_recipes.getUUID(6)}%",
rp_id=rp_id,
item_type=request.get_json()['item_type'],
item_name=request.get_json()['item_name'],
@ -186,7 +186,7 @@ def postCustomItem():
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'})
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed!'})
@recipes_api.route('/recipe/postSKUItem', methods=["POST"])
@recipes_api.route('/postSKUItem', methods=["POST"])
@login_required
def postSKUItem():
""" post a recipe item to the database by passing a recipe_id and item_id
@ -201,7 +201,6 @@ def postSKUItem():
item_id = int(request.get_json()['item_id'])
site_name = session['selected_site']
item = database_recipes.getItemData(site_name, (item_id, ))
print(item)
recipe_item = db.RecipesTable.ItemPayload(
uuid=item['barcode'],
rp_id=recipe_id,
@ -217,7 +216,7 @@ def postSKUItem():
return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'})
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'})
@recipes_api.route('/recipe/postImage/<recipe_id>', methods=["POST"])
@recipes_api.route('/postImage/<recipe_id>', methods=["POST"])
@login_required
def uploadImage(recipe_id):
""" post an image for a recipe into the database and files by passing the recipe_id and picture_path
@ -239,7 +238,7 @@ def uploadImage(recipe_id):
database_recipes.postUpdateRecipe(site_name, {'id': recipe_id, 'update': {'picture_path': file.filename.replace(" ", "_")}})
return jsonify({'error': False, 'message': 'Recipe was updated successfully!'})
@recipes_api.route('/recipe/getImage/<recipe_id>')
@recipes_api.route('/getImage/<recipe_id>')
@login_required
def get_image(recipe_id):
""" get the picture path for a recipe by passing teh recipe id in the path
@ -258,7 +257,7 @@ def get_image(recipe_id):
picture_path = database_recipes.getPicturePath(site_name, (recipe_id,))
return send_from_directory('static/pictures/recipes', picture_path)
@recipes_api.route('/recipe/deleteRecipeItem', methods=["POST"])
@recipes_api.route('/deleteRecipeItem', methods=["POST"])
@login_required
def deleteRecipeItem():
""" delete recipe item from database by passing the recipe item ID
@ -276,7 +275,7 @@ def deleteRecipeItem():
return jsonify({'recipe': recipe, 'error': False, 'message': f'Recipe Item {deleted_item['item_name']} was deleted successful!'})
return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'})
@recipes_api.route('/recipe/saveRecipeItem', methods=["POST"])
@recipes_api.route('/saveRecipeItem', methods=["POST"])
@login_required
def saveRecipeItem():
""" post an update to a recipe item in the database by passing the recipe item ID and an update

View File

@ -195,7 +195,7 @@ async function saveLineItem(item){
}
async function getRecipe() {
const url = new URL('/recipe/getRecipe', window.location.origin)
const url = new URL('/recipes/getRecipe', window.location.origin)
url.searchParams.append('id', recipe_id);
const response = await fetch(url)
data = await response.json()
@ -203,7 +203,7 @@ async function getRecipe() {
}
async function getImage(){
await fetch(`/recipe/getImage/${recipe.id}`)
await fetch(`/recipes/getImage/${recipe.id}`)
.then(response => response.blob())
.then(imageBlob => {
const imageURL = URL.createObjectURL(imageBlob);
@ -220,7 +220,7 @@ async function addCustomItem() {
uom: document.getElementById('customUOM').value,
links: {main: document.getElementById('customWeblink').value}
}
const response = await fetch(`/recipe/postCustomItem`, {
const response = await fetch(`/recipes/postCustomItem`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -248,7 +248,7 @@ async function addCustomItem() {
}
async function addSKUItem(item_id) {
const response = await fetch(`/recipe/postSKUItem`, {
const response = await fetch(`/recipes/postSKUItem`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -279,11 +279,7 @@ async function postUpdate() {
let description = document.getElementById('recipeDescription').value
updated.description = description
console.log(updated)
const response = await fetch(`/recipe/postUpdate`, {
const response = await fetch(`/recipes/postUpdate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -313,7 +309,7 @@ async function updateImage() {
const formData = new FormData();
formData.append('file', fileInput.files[0]);
await fetch(`/recipe/postImage/${recipe.id}`, {
await fetch(`/recipes/postImage/${recipe.id}`, {
method: 'POST',
body: formData
})
@ -458,7 +454,7 @@ async function updateItemsPaginationElement() {
}
async function fetchItems() {
const url = new URL('/recipe/getItems', window.location.origin);
const url = new URL('/recipes/getItems', window.location.origin);
url.searchParams.append('page', pagination_current);
url.searchParams.append('limit', items_limit);
url.searchParams.append('search_string', search_string);

View File

@ -84,7 +84,7 @@ async function replenishInstructions() {
}
async function getRecipe() {
const url = new URL('/recipe/getRecipe', window.location.origin)
const url = new URL('/recipes/getRecipe', window.location.origin)
url.searchParams.append('id', recipe_id);
const response = await fetch(url)
data = await response.json()
@ -93,7 +93,7 @@ async function getRecipe() {
async function getImage(){
console.log('fetching image!')
await fetch(`/recipe/getImage/${recipe.id}`)
await fetch(`/recipes/getImage/${recipe.id}`)
.then(response => response.blob())
.then(imageBlob => {
const imageURL = URL.createObjectURL(imageBlob);

View File

@ -107,12 +107,12 @@ async function replenishRecipesTable() {
let viewOp = document.createElement('a')
viewOp.innerHTML = `view <span uk-icon="icon: eye"></span>`
viewOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
viewOp.href = `/recipe/view/${recipes[i].id}`
viewOp.href = `/recipes/view/${recipes[i].id}`
let editOp = document.createElement('a')
editOp.innerHTML = `edit <span uk-icon="icon: pencil"></span>`
editOp.setAttribute('class', 'uk-button uk-button-default uk-button-small')
editOp.href = `/recipe/edit/${recipes[i].id}`
editOp.href = `/recipes/edit/${recipes[i].id}`
buttonGroup.append(viewOp, editOp)
opsCell.append(buttonGroup)

View File

@ -159,5 +159,5 @@
<script>
const session = {{session|tojson}}
</script>
<script src="{{ url_for('static', filename='handlers/recipesListHandler.js') }}"></script>
<script src="{{ url_for('recipes_api.static', filename='js/recipesListHandler.js') }}"></script>
</html>

View File

@ -328,5 +328,5 @@
const recipe_id = {{recipe_id|tojson}}
const units = {{units|tojson}}
</script>
<script src="{{ url_for('static', filename='handlers/recipeEditHandler.js') }}"></script>
<script src="{{ url_for('recipes_api.static', filename='js/recipeEditHandler.js') }}"></script>
</html>

View File

@ -124,5 +124,5 @@
const session = {{session|tojson}}
const recipe_id = {{recipe_id|tojson}}
</script>
<script src="{{ url_for('static', filename='handlers/recipeViewHandler.js') }}"></script>
<script src="{{ url_for('recipes_api.static', filename='js/recipeViewHandler.js') }}"></script>
</html>

View File

@ -1842,3 +1842,6 @@
2025-04-26 18:29:30.532818 --- ERROR --- DatabaseError(message=''module' object is not callable. Did you mean: 'config.config(...)'?',
payload=(10, 0),
sql='SELECT *, (SELECT COALESCE(array_agg(row_to_json(g)), '{}') FROM main_recipe_items g WHERE rp_id = main_recipes.id) AS rp_items FROM main_recipes LIMIT %s OFFSET %s;')
2025-04-26 21:18:52.710178 --- ERROR --- DatabaseError(message='duplicate key value violates unique constraint "test_recipe_items_uuid_key"DETAIL: Key (uuid)=(%X0031BMH6V%) already exists.',
payload=('%X0031BMH6V%', 3, 'sku', 'Torani Peppermint syrup', 1, 1.0, 2020, '{}'),
sql='INSERT INTO test_recipe_items(uuid, rp_id, item_type, item_name, uom, qty, item_id, links) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING *;')

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -32,7 +32,7 @@ app.register_blueprint(workshop_api)
app.register_blueprint(receipts_API.receipt_api)
app.register_blueprint(shopping_list_API.shopping_list_api)
app.register_blueprint(group_api.groups_api)
app.register_blueprint(recipes_api.recipes_api)
app.register_blueprint(recipes_api.recipes_api, url_prefix='/recipes')