Lots of base additons

This commit is contained in:
Jadowyne Ulve 2024-10-11 22:35:40 -05:00
parent 9a57fa7ad6
commit f042c7ca82
31 changed files with 556 additions and 89 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

88
api.py
View File

@ -4,12 +4,59 @@ from config import config
database_api= Blueprint('database_api', __name__)
def paginate_with_params(cur, limit, offset, params):
sql = f"SELECT * FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id"
count = f"SELECT COUNT(*) FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id"
# WHERE search_string LIKE '%{search_string}%'
strings = []
count_strings = []
if params['search_string'] != "":
s = params['search_string']
strings.append(f" search_string LIKE '%{s}%'")
count_strings.append(f" search_string LIKE '%{s}%'")
if params['view'] == 1:
s = params['view']
strings.append(f" main_logistics_info.quantity_on_hand <> 0.00")
count_strings.append(f" main_logistics_info.quantity_on_hand <> 0.00")
# LIMIT {limit} OFFSET {offset};"
if len(strings) > 0:
sql = f"{sql} WHERE{" AND".join(strings)}"
if len(count_strings) > 0:
count = f"{count} WHERE{" AND".join(count_strings)}"
sql = f"{sql} ORDER BY main_logistics_info.quantity_on_hand LIMIT {limit} OFFSET {offset};"
count = f"{count};"
print(count)
print(sql)
cur.execute(sql)
pantry_inventory = cur.fetchall()
cur.execute(count)
count = cur.fetchone()[0]
return pantry_inventory, count
def paginate_default(cur, limit, offset):
sql = f"SELECT * FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id LIMIT %s OFFSET %s;"
cur.execute(sql, (limit, offset))
pantry_inventory = cur.fetchall()
cur.execute("SELECT COUNT(*) FROM main_items;")
count = cur.fetchone()[0]
return pantry_inventory, count
@database_api.route("/getItems")
def pagninate_items():
print("hello")
page = int(request.args.get('page', 1))
limit = int(request.args.get('limit', 10))
search_string = str(request.args.get('search_text', ""))
sort_order = int(request.args.get('sort_order', 1))
view = int(request.args.get('view', 0))
offset = (page - 1) * limit
@ -20,27 +67,23 @@ def pagninate_items():
with psycopg2.connect(**database_config) as conn:
try:
with conn.cursor() as cur:
if search_string != "":
sql = f"SELECT * FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id WHERE search_string LIKE '%{search_string}%' LIMIT {limit} OFFSET {offset};"
cur.execute(sql)
pantry_inventory = cur.fetchall()
cur.execute(f"SELECT COUNT(*) FROM main_items WHERE search_string LIKE '%{search_string}%';")
count = cur.fetchone()[0]
else:
sql = f"SELECT * FROM main_items LEFT JOIN main_logistics_info ON main_items.logistics_info_id = main_logistics_info.id LIMIT %s OFFSET %s;"
cur.execute(sql, (limit, offset))
pantry_inventory = cur.fetchall()
cur.execute("SELECT COUNT(*) FROM main_items;")
count = cur.fetchone()[0]
print(sql)
print(count, math.ceil(count/limit))
pantry_inventory, count = paginate_with_params(
cur, limit, offset,
{'search_string': search_string,
'view': view}
)
except (Exception, psycopg2.DatabaseError) as error:
print(error)
if sort_order == 0:
pantry_inventory = sorted(pantry_inventory, key=lambda x: x[1])
if sort_order == 1:
pantry_inventory = sorted(pantry_inventory, key=lambda x: x[2])
if sort_order == 2:
pantry_inventory = sorted(pantry_inventory, key=lambda x: x[18])
return jsonify({'items': pantry_inventory, "end": math.ceil(count/limit)})
@database_api.route("/getItem")
@ -64,3 +107,16 @@ def get_item():
print(error)
return render_template(f"item_page/index.html", item=item)
@database_api.route("/addGroup")
def addGroup():
name = str(request.args.get('name', ""))
description = str(request.args.get('description', ""))
group_type = str(request.args.get('type', ""))
state = "FAILED"
if name or description or group_type == "":
print("this is empty")
return jsonify({'state': state})

14
main.py
View File

@ -310,6 +310,11 @@ def delete_site(site_name):
drop_table(f'sites/{site_name}/sql/drop/logistics_info.sql')
drop_table(f'sites/{site_name}/sql/drop/zones.sql')
drop_table(f'sites/{site_name}/sql/drop/locations.sql')
drop_table(f'sites/{site_name}/sql/drop/vendors.sql')
drop_table(f'sites/{site_name}/sql/drop/receipt_items.sql')
drop_table(f'sites/{site_name}/sql/drop/receipts.sql')
drop_table(f'sites/{site_name}/sql/drop/recipes.sql')
drop_table(f'sites/{site_name}/sql/drop/shopping_lists.sql')
def create_site(site_name):
@ -326,6 +331,12 @@ def create_site(site_name):
create_table(f'sites/{site_name}/sql/create/item.sql')
create_table(f'sites/{site_name}/sql/create/zones.sql')
create_table(f'sites/{site_name}/sql/create/locations.sql')
create_table(f'sites/{site_name}/sql/create/vendors.sql')
create_table(f'sites/{site_name}/sql/create/receipt_items.sql')
create_table(f'sites/{site_name}/sql/create/receipts.sql')
create_table(f'sites/{site_name}/sql/create/recipes.sql')
create_table(f'sites/{site_name}/sql/create/shopping_lists.sql')
sql = f"INSERT INTO {site_name}_zones(name) VALUES (%s) RETURNING id;"
sqltwo = f"INSERT INTO {site_name}_locations(uuid, name, zone_id, items) VALUES (%s, %s, %s, %s);"
@ -411,6 +422,7 @@ def parse_csv(path_to_csv):
if line[0] != "id":
payload["item_info"]["packaging"] = line[10]
payload["item_info"]["uom"] = line[13]
if line[15] != "":
payload["item_info"]["cost"] = line[15]
if line[17] != "None":
payload["item_info"]["safety_stock"] = line[17]
@ -432,4 +444,4 @@ if __name__ == "__main__":
for k, v in items.items():
print(f"{k}: {v}")
"""
parse_csv(r"C:\\Users\\jadow\Downloads\\2024-10-02-Pantry.csv")
parse_csv(r"C:\\Users\\jadow\\Documents\\code\\postgresql python\\postgresql-python\\2024-10-02-Pantry.csv")

View File

@ -6,6 +6,22 @@ Manage.py is where the databases and configuration is set up. Its a CLI for quic
MyPantry App.
"""
def rename_unique_sql(site_name):
files = os.walk(f"sites/{site_name}/sql/unique")
sql_files = []
for file in files:
sql_files = file[2]
for file_name in sql_files:
words = None
with open(f"sites/{site_name}/sql/unique/{file_name}", "r") as file:
words = file.read()
words = words.replace("%sitename%", site_name)
with open(f"sites/{site_name}/sql/unique/{file_name}", "w") as file:
file.write(words)
def rename_drop_sql(site_name):
files = os.walk(f"sites/{site_name}/sql/drop")
@ -60,6 +76,7 @@ def create():
shutil.copytree(f"sites/default/sql", f"sites/{site_name}/sql")
rename_create_sql(site_name)
rename_drop_sql(site_name)
rename_unique_sql(site_name)
with open(f"sites/{site_name}/site.ini", "w+") as config:
config.write(f"[site]\n")

View File

@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS %sitename%_items(
barcode VARCHAR(255) NOT NULL,
item_name VARCHAR(255) NOT NULL,
brand INTEGER,
description TEXT;
tags TEXT [],
links JSONB,
item_info_id INTEGER NOT NULL,

View File

@ -6,4 +6,4 @@ CREATE TABLE IF NOT EXISTS %sitename%_receipt_items (
qty FLOAT8 NOT NULL,
data JSONB,
status VARCHAR (64)
)
);

View File

@ -5,4 +5,4 @@ CREATE TABLE IF NOT EXISTS %sitename%_vendors (
creation_date TIMESTAMP NOT NULL,
created_by TIMESTAMP NOT NULL,
phone_number VARCHAR(32)
)
);

View File

@ -0,0 +1 @@
DROP TABLE %sitename%_receipt_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %sitename%_receipts CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %sitename%_recipes CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %sitename%_shopping_lists CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE %sitename%_vendors CASCADE;

View File

@ -9,36 +9,37 @@ WHERE %sitename%_items.id=%s;
01 - barcode
02 - item_name
03 - brand (id)
04 - tags
05 - links
06 - item_info_id
07 - logistics_info_id
08 - food_info_id
09 - row_type
10 - item_type
11 - search_string
12 - logistics_info_id
13 - barcode
14 - primary_location
15 - auto_issue_location
16 - dynamic_locations
17 - location_data
18 - quantity_on_hand
19 - item_info_id
20 - barcode
21 - linked_items
22 - shopping_lists
23 - recipes
24 - groups
25 - packaging
26 - uom
27 - cost
28 - safety_stock
29 - lead_time_days
30 - ai_pick
31 - food_info_id
32 - food_groups
33 - ingrediants
34 - nutrients
35 - expires
04 - description
05 - tags
06 - links
07 - item_info_id
08 - logistics_info_id
09 - food_info_id
10 - row_type
11 - item_type
12 - search_string
13 - logistics_info_id
14 - barcode
15 - primary_location
16 - auto_issue_location
17 - dynamic_locations
18 - location_data
19 - quantity_on_hand
20 - item_info_id
21 - barcode
22 - linked_items
23 - shopping_lists
24 - recipes
25 - groups
26 - packaging
27 - uom
28 - cost
29 - safety_stock
30 - lead_time_days
31 - ai_pick
32 - food_info_id
33 - food_groups
34 - ingrediants
35 - nutrients
36 - expires
*/

View File

@ -1,6 +1,6 @@
[site]
site_name=main
site_owner=jadowyne
site_owner=
email=
[defaults]

View File

@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS main_items(
item_name VARCHAR(255) NOT NULL,
brand INTEGER,
tags TEXT [],
links TEXT [],
links JSONB,
item_info_id INTEGER NOT NULL,
logistics_info_id INTEGER NOT NULL,
food_info_id INTEGER,

View File

@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS main_receipt_items (
id SERIAL PRIMARY KEY,
type VARCHAR(255) NOT NULL,
barcode VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
qty FLOAT8 NOT NULL,
data JSONB,
status VARCHAR (64)
);

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS main_receipts (
id SERIAL PRIMARY KEY,
receipt_id INTEGER NOT NULL,
receipt_status VARCHAR (64) NOT NULL,
date_submitted TIMESTAMP NOT NULL,
submitted_by INTEGER NOT NULL,
vendor_id INTEGER,
files JSONB,
UNIQUE(receipt_id)
);

View File

@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS main_recipes (
id SERIAL PRIMARY KEY,
name VARCHAR,
author INTEGER,
description TEXT,
creation_date TIMESTAMP,
custom_items JSONB,
pantry_items JSONB,
group_items JSONB,
instructions TEXT [],
picture_path TEXT
);

View File

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS main_shopping_lists (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
pantry_items JSONB,
custom_items JSONB,
recipes JSONB,
groups JSONB,
author INTEGER,
creation_date TIMESTAMP,
type VARCHAR(64),
UNIQUE(name)
);

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS main_vendors (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address VARCHAR(255),
creation_date TIMESTAMP NOT NULL,
created_by TIMESTAMP NOT NULL,
phone_number VARCHAR(32)
);

View File

@ -0,0 +1 @@
DROP TABLE main_receipt_items CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE main_receipts CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE main_recipes CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE main_shopping_lists CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE main_vendors CASCADE;

View File

@ -3,3 +3,42 @@ SELECT * FROM main_items
LEFT JOIN main_item_info ON main_items.item_info_id = main_item_info.id
LEFT JOIN main_food_info ON main_items.food_info_id = main_food_info.id
WHERE main_items.id=%s;
/*
00 - item_id
01 - barcode
02 - item_name
03 - brand (id)
04 - tags
05 - links
06 - item_info_id
07 - logistics_info_id
08 - food_info_id
09 - row_type
10 - item_type
11 - search_string
12 - logistics_info_id
13 - barcode
14 - primary_location
15 - auto_issue_location
16 - dynamic_locations
17 - location_data
18 - quantity_on_hand
19 - item_info_id
20 - barcode
21 - linked_items
22 - shopping_lists
23 - recipes
24 - groups
25 - packaging
26 - uom
27 - cost
28 - safety_stock
29 - lead_time_days
30 - ai_pick
31 - food_info_id
32 - food_groups
33 - ingrediants
34 - nutrients
35 - expires
*/

View File

@ -4,78 +4,177 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8" />
<title>My Pantry</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/css/materialize.min.css" />
<!-- Material Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<!-- Material Symbols - Outlined Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
<!-- Material Symbols - Rounded Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded" rel="stylesheet" />
<!-- Material Symbols - Sharp Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/js/materialize.min.js"></script>
</head>
<style>
.hand-pointer {
cursor: pointer;
}
[type="radio"]:checked + span:after {
border: 2px solid rgb(0 128 0 / 30%); /* Outline color */
background-color: rgb(0 128 0 / 30%); /* Fill color */
}
</style>
<body>
<div class="container section">
<div class="container section" style="padding-bottom: 72px;">
<div class="row">
<div class="col s9 m6 offset-m3 input-field outlined align-center">
<i class="material-icons prefix">search</i>
<input style="border-radius: 20px; border: 1px solid #ccc;" id="search" name="search" type="search" placeholder="Search" value="">
</div>
<div class="col s3">
<a class="btn waves-effect waves-light center-align right tooltipped" data-position="bottom" data-tooltip="Open up filter options." style="margin-top: 5px;" onclick="hideFilters()"><i class="material-icons">tune</i></a>
<a class="btn waves-effect waves-light center-align right tooltipped green lighten-3 black-text text-darken-2 z-depth-0" data-position="bottom" data-tooltip="Open up filter options." style="margin-right: 5px; margin-top:0px; border-radius: 20px 10px 20px 10px;" onclick="hideFilters()"><i class="material-icons">tune</i></a>
</div>
<div class="col s12 hide" id="filter_options">
<div class="row">
<div class="col s12 hide" id="filter_options" style="padding: 20px">
<!-- This is for basic views -->
<div class="row center">
<div class="col s12">
<p>Item Limit</p>
<p>Change Views</p>
</div>
<div class="col s2">
<div class="col s6 m4 l2">
<label>
<input name="group3" type="radio" checked onclick="changeView(0)"/>
<span>All</span>
</label>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group3" type="radio" onclick="changeView(1)"/>
<span>Non Zero Items</span>
</label>
</div>
<div class="col s12 divider"></div>
</div>
<!-- This is for sorting values -->
<div class="row center">
<div class="col s12">
<p>Sort Items By</p>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group2" type="radio" onclick="changeSort(0)"/>
<span>Barcode</span>
</label>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group2" type="radio" checked onclick="changeSort(1)"/>
<span>Item Name</span>
</label>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group2" type="radio" onclick="changeSort(2)"/>
<span>Quantity on Hand</span>
</label>
</div>
<div class="col s12 divider"></div>
</div>
<!-- Set the number of items -->
<div class="row center">
<div class="col s12">
<p>Set Items Per Page</p>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" checked onclick="changeLimit(25)"/>
<span>25 items</span>
</label>
</div>
<div class="col s2">
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" onclick="changeLimit(50)"/>
<span>50 items</span>
</label>
</div>
<div class="col s2">
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" onclick="changeLimit(75)"/>
<span>75 itesm</span>
</label>
</div>
<div class="col s2">
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" onclick="changeLimit(100)"/>
<span>100 items</span>
</label>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" onclick="changeLimit(150)"/>
<span>150 items</span>
</label>
</div>
<div class="col s6 m4 l2">
<label>
<input name="group1" type="radio" onclick="changeLimit(200)"/>
<span>200 items</span>
</label>
</div>
<div class="col s12 divider"></div>
</div>
</div>
<div class="col s12">
<div class="collection" id="collection_list">
<div class="col s12 z-depth-0">
<div class="z-depth-0" id="cards">
</div>
</div>
<div class="col s12 center" id="pagination_list">
<ul class="pagination">
<li id="first" class="waves-effect"><a><i class="material-icons">first_page</i></a></li>
<li id="back" class="waves-effect"><a><i class="material-icons">chevron_left</i></a></li>
<li id="current_page" class="flow-text">page_number</li>
<li id="forward" class="waves-effect"><a><i class="material-icons">chevron_right</i></a></li>
<li id="last" class="waves-effect"><a><i class="material-icons">last_page</i></a></li>
<li id="first" class="waves-effect hand-pointer"><a class="green lighten-3" style="display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px;"><i class="material-icons">first_page</i></a></li>
<li id="back" class="waves-effect hand-pointer" ><a class="green lighten-3" style="display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px;"><i class="material-icons">chevron_left</i></a></li>
<li id="current_page" style="padding-top: 7px; padding-left: 5px; padding-right: 5px; font-size: 18px;">page_number</li>
<li id="forward" class="waves-effect hand-pointer"><a class="green lighten-3" style="display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px;"><i class="material-icons">chevron_right</i></a></li>
<li id="last" class="waves-effect hand-pointer"><a class="green lighten-3" style="display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px;"><i class="material-icons">last_page</i></a></li>
</ul>
</div>
</div>
</div>
<div class="fixed-action-btn">
<a class="btn-floating btn-large">
<i class="large material-icons">more_vert</i>
</a>
<ul>
<li><a class="btn-floating blue darken-1"><i class="material-icons">playlist_add</i></a></li>
<li><a class="btn-floating green darken-1"><i class="material-icons">download</i></a></li>
</ul>
</div>
</body>
<script>
let current_page = 1
let end_page = 10
let sort_order = 1
let view = 0
let limit = 50
let filter_state = "hidden"
let searchText = ""
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.collapsible');
var instances = M.Collapsible.init(elems, {
// specify options here
});
});
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.fixed-action-btn');
var instances = M.FloatingActionButton.init(elems, {
// specify options here
});
});
document.addEventListener('DOMContentLoaded', function() {
update_list()
});
@ -108,6 +207,10 @@
url.searchParams.append('page', current_page);
url.searchParams.append('limit', limit);
url.searchParams.append('search_text', searchText);
url.searchParams.append('sort_order', sort_order);
url.searchParams.append('view', view);
fetch(url)
.then(response => response.json())
@ -127,24 +230,79 @@
document.getElementById('last').classList.add("waves-effect")
};
const collection = document.getElementById('collection_list');
collection.style = "border: 0px; gap: 12px;"
while(collection.firstChild){
collection.removeChild(collection.firstChild);
}
//<ul class="collapsible">
// <li>
// <div class="collapsible-header"><i class="material-icons">filter_drama</i>First</div>
//<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
// </li>
//</ul>
const cards = document.getElementById("cards")
const dummy_div = document.createElement('div')
const list_collapsible = document.createElement('ul')
list_collapsible.classList.add("collapsible")
list_collapsible.classList.add("popout")
list_collapsible.style = "background: white;"
data.items.forEach(item => {
const collection_item = document.createElement('a');
collection_item.classList.add('collection-item');
collection_item.classList.add('truncate');
collection_item.href = `/getItem?id=${item[0]}`
collection_item.style = "border-radius: 20px; border: 1px solid #ccc; margin-top: 5px;"
let qty = item[18]
let roundedQty = qty.toFixed(2)
collection_item.innerHTML = `${item[2]}<span class="badge hide-on-small-only indigo lighten-4" style="border-radius: 20px;" data-badge-caption="">${roundedQty}</span>`;
collection.appendChild(collection_item);
})
var list_item = document.createElement('li')
list_item.classList.add("z-depth-0")
list_item.style = "background: white;"
var header = document.createElement("div")
header.classList.add("collapsible-header")
header.style = "box-shadow: none !important; background: white; border: 1px solid rgb(150 150 150 / 30%); border-radius: 10px 10px 0px 0px;"
header.innerHTML = `<i class='material-symbols-outlined'>grocery</i>${item[2]}
<span class="badge green lighten-4 black-text text-darken-2 z-depth-0" style="border-radius: 5px;">Qty: ${roundedQty}</span>`
var body = document.createElement('div')
body.classList.add("collapsible-body")
body.style = "box-shadow: none !important; background: rgb(0 128 0 / 10%); border: 1px solid rgb(150 150 150 / 30%); border-radius: 0px 0px 10px 10px;"
var description = document.createElement('div')
description.classList.add("col")
description.classList.add("s12")
description.innerHTML = `
<span>Lorem ipsum dolor sit amet. This is a description for ${item[2]}</span>
<div class="divider s12" style="margin-bottom: 5px; margin-top: 5px;"></div>`
var button_group = document.createElement('div')
button_group.classList.add("row")
button_group.style = "margin-bottom: 0px; padding-bottom: 0px;"
button_group.innerHTML = `
<div class="col s12" style="align-items: center;">
<a class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="bottom" data-tooltip="Edit Item" style="display: inline-flex; border-radius: 20px 10px 20px 10px;">
<i class='material-icons'>edit</i>
</a>
<a class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="left" data-tooltip="Transactions" style="display: inline-flex; margin-right: 5px; margin-top:0px; border-radius: 20px 10px 20px 10px;">
<i class='material-icons'>list_alt</i>
</a>
</div>`
body.appendChild(description)
body.appendChild(button_group)
list_item.appendChild(header)
list_item.appendChild(body)
list_collapsible.appendChild(list_item)
});
dummy_div.appendChild(list_collapsible)
cards.innerHTML = dummy_div.innerHTML
var elems = document.querySelectorAll('.collapsible');
var instances = M.Collapsible.init(elems, {
// specify options here
});
var elems = document.querySelectorAll('.tooltipped');
var instances = M.Tooltip.init(elems, {
// specify options here
});
document.getElementById("current_page").innerHTML = `${String(current_page)} / ${String(end_page)}`
})
@ -157,6 +315,16 @@
update_list()
};
function changeSort(order){
sort_order = order
update_list()
}
function changeView(view_num){
view = view_num
update_list()
}
function hideFilters(){
if (filter_state == "hidden"){
document.getElementById("filter_options").classList.remove("hide");

108
templates/workshop.html Normal file
View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8" />
<title>Workshop</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/css/materialize.min.css" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/js/materialize.min.js"></script>
</head>
<body>
<div class="container">
<div class="section">
<div class="row">
<div class="col s12">
<div class="row">
<div class="col s12 m9" style="background-color: whitesmoke;">
<p class="flow-text" style="text-align: center; padding: 10px;"> Welcome to you personalized workshop, this is where you can add/create/modify
alot of the items and functions in your site. These modals will walk you through what basic info you will need
in order to further expand on your site.</p>
</div>
<div class="col s12 m3" style="background-color: aliceblue;">
<div class="col s6 m6 m-2">
<a class="btn elevated green modal-trigger" href="#modal1" style="width: 100%;">Add Group</a>
</div>
<div class="col s6 m6 m-2">
<button class="btn elevated orange" style="width: 100%;">Add Item</button>
</div>
<div class="col s6 m6 m-2">
<button class="btn elevated blue" style="width: 100%;">Add Shopping List</button>
</div>
<div class="col s6 m6 m-2">
<button class="btn elevated purple" style="width: 100%;">Add Recipe</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Adding a Group...</h4>
<div class="row">
<div class="col s12">
<div class="card-panel">
<span class="blue-text">Groups are internal "grouping" of items that can be of the same type, tag, process, etc. The point of them is that you
can keep track of all of one thing in a list for quick reference.</span>
</div>
</div>
<div class="col s12 m6 input-field outlined p-2">
<input id="group_name" type="text" placeholder=" " maxlength="64">
<label for="group_name">Group Name</label>
<!--<span class="supporting-text">Supporting Text</span>-->
</div>
<div class="input-field col s12 m6 p-2">
<select id="group_type">
<option value="plain" selected>Plain Group</option>
<option value="exclusive">Exclusive Group</option>
<option value="inclusive">Inclusive Group</option>
</select>
<label for="group_type">Group Type</label>
</div>
<div class="input-field col s12 p-2">
<textarea id="group_description" class="materialize-textarea" placeholder="A short description for what this group represents..."></textarea>
<label for="group_description">Group Description</label>
</div>
</div>
</div>
<div class="modal-footer">
<a onclick="addGroup()" class="waves-effect btn">Add</a>
</div>
</div>
</body>
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {
// specify options here
});
});
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems, {
// specify options here
});
});
function addGroup(){
var name = document.getElementById("group_name").value
var description = document.getElementById("group_description").value
var type = document.getElementById("group_type").value
const url = new URL('/addGroup', window.location.origin);
url.searchParams.append('name', name);
url.searchParams.append('description', description);
url.searchParams.append('type', type);
fetch(url)
.then(response => response.json())
.then(data => {
console.log(data)
})
}
</script>
</html>

View File

@ -4,6 +4,9 @@ app = Flask(__name__)
app.register_blueprint(api.database_api)
@app.route("/workshop")
def workshop():
return render_template("workshop.html")
@app.route("/")
def home():