Moved all static files for recipe_api
This commit is contained in:
parent
9f4084a4d7
commit
987a665f72
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
||||
@ -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,21 +105,19 @@ 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,
|
||||
description=recipe_description
|
||||
)
|
||||
recipe = database_recipes.postAddRecipe(site_name, recipe.payload())
|
||||
webpush.push_ntfy('New Recipe', f"New Recipe added to {site_name}; {recipe_name}! {recipe_description} \n http://test.treehousefullofstars.com/recipe/view/{recipe['id']} \n http://test.treehousefullofstars.com/recipe/edit/{recipe['id']}")
|
||||
recipe = db.RecipesTable.Payload(
|
||||
name=recipe_name,
|
||||
author=user_id,
|
||||
description=recipe_description
|
||||
)
|
||||
recipe = database_recipes.postAddRecipe(site_name, recipe.payload())
|
||||
webpush.push_ntfy('New Recipe', f"New Recipe added to {site_name}; {recipe_name}! {recipe_description} \n http://test.treehousefullofstars.com/recipe/view/{recipe['id']} \n http://test.treehousefullofstars.com/recipe/edit/{recipe['id']}")
|
||||
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
|
||||
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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)
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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 *;')
|
||||
BIN
static/pictures/recipes/20250425_163102.jpg
Normal file
BIN
static/pictures/recipes/20250425_163102.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
@ -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')
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user