test
This commit is contained in:
parent
76c3f33b55
commit
e21fab65ea
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
143
api.py
143
api.py
@ -155,6 +155,73 @@ def pagninate_items():
|
|||||||
|
|
||||||
return jsonify({'items': pantry_inventory, "end": math.ceil(count/limit)})
|
return jsonify({'items': pantry_inventory, "end": math.ceil(count/limit)})
|
||||||
|
|
||||||
|
@database_api.route("/getTransactions")
|
||||||
|
def pagninate_transactions():
|
||||||
|
item_id = request.args.get('id', 1)
|
||||||
|
page = int(request.args.get('page', 1))
|
||||||
|
limit = int(request.args.get('limit', 10))
|
||||||
|
site_name = session['selected_site']
|
||||||
|
|
||||||
|
offset = (page - 1) * limit
|
||||||
|
count = 0
|
||||||
|
transactions = []
|
||||||
|
|
||||||
|
database_config = config()
|
||||||
|
with psycopg2.connect(**database_config) as conn:
|
||||||
|
try:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
|
||||||
|
cur.execute(f"SELECT logistics_info_id FROM {site_name}_items WHERE id={item_id};")
|
||||||
|
logistics_info_id = cur.fetchone()[0]
|
||||||
|
sql = f"SELECT * FROM {site_name}_transactions WHERE logistics_info_id={logistics_info_id} LIMIT {limit} OFFSET {offset};"
|
||||||
|
count = f"SELECT COUNT(*) FROM {site_name}_transactions WHERE logistics_info_id={logistics_info_id};"
|
||||||
|
cur.execute(sql)
|
||||||
|
transactions = cur.fetchall()
|
||||||
|
cur.execute(count)
|
||||||
|
count = cur.fetchone()[0]
|
||||||
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
|
print(error)
|
||||||
|
|
||||||
|
return jsonify({'transactions': transactions, "end": math.ceil(count/limit)})
|
||||||
|
|
||||||
|
@database_api.route("/getLocations")
|
||||||
|
def get_locations():
|
||||||
|
zone_name = request.args.get('zone', 1)
|
||||||
|
database_config = config()
|
||||||
|
site_name = session['selected_site']
|
||||||
|
locations = []
|
||||||
|
with psycopg2.connect(**database_config) as conn:
|
||||||
|
try:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
sql = f"SELECT id FROM {site_name}_zones WHERE name=%s;"
|
||||||
|
cur.execute(sql, (zone_name,))
|
||||||
|
zone_id = cur.fetchone()[0]
|
||||||
|
|
||||||
|
sqltwo = f"SELECT name FROM {site_name}_locations WHERE zone_id=%s;"
|
||||||
|
cur.execute(sqltwo, (zone_id, ))
|
||||||
|
locations = [location[0] for location in cur.fetchall()]
|
||||||
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
|
print(error)
|
||||||
|
|
||||||
|
print(locations)
|
||||||
|
return jsonify(locations=locations)
|
||||||
|
|
||||||
|
@database_api.route("/getZones")
|
||||||
|
def get_zones():
|
||||||
|
database_config = config()
|
||||||
|
site_name = session['selected_site']
|
||||||
|
zones = []
|
||||||
|
with psycopg2.connect(**database_config) as conn:
|
||||||
|
try:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
sql = f"SELECT name FROM {site_name}_zones;"
|
||||||
|
cur.execute(sql)
|
||||||
|
zones = [zone[0] for zone in cur.fetchall()]
|
||||||
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
|
print(error)
|
||||||
|
print(zones)
|
||||||
|
return jsonify(zones=zones)
|
||||||
|
|
||||||
@database_api.route("/getItem")
|
@database_api.route("/getItem")
|
||||||
def get_item():
|
def get_item():
|
||||||
id = int(request.args.get('id', 1))
|
id = int(request.args.get('id', 1))
|
||||||
@ -181,7 +248,7 @@ def get_item():
|
|||||||
except (Exception, psycopg2.DatabaseError) as error:
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
print(error)
|
print(error)
|
||||||
|
|
||||||
return render_template(f"items/item.html", item=item, current_site=site_name, sites=sites['sites'])
|
return jsonify(item=item)
|
||||||
|
|
||||||
@database_api.route("/addItem")
|
@database_api.route("/addItem")
|
||||||
def addItem():
|
def addItem():
|
||||||
@ -201,6 +268,8 @@ def addItem():
|
|||||||
payload["logistics_info"]["primary_location"] = uuid
|
payload["logistics_info"]["primary_location"] = uuid
|
||||||
payload["logistics_info"]["auto_issue_location"] = uuid
|
payload["logistics_info"]["auto_issue_location"] = uuid
|
||||||
|
|
||||||
|
tags = main.lst2pgarr([])
|
||||||
|
links = json.dumps({})
|
||||||
|
|
||||||
database_config = config()
|
database_config = config()
|
||||||
with psycopg2.connect(**database_config) as conn:
|
with psycopg2.connect(**database_config) as conn:
|
||||||
@ -214,7 +283,7 @@ def addItem():
|
|||||||
if not food_info_id:
|
if not food_info_id:
|
||||||
return jsonify({'state': str(food_info_id)})
|
return jsonify({'state': str(food_info_id)})
|
||||||
|
|
||||||
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, description, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', '{description}', {item_info_id}, {logistics_info_id}, {food_info_id}, '{item_type}', '{subtype}', '{barcode}%{name}') RETURNING *;"
|
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, tags, links, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', '{tags}', '{links}', {item_info_id}, {logistics_info_id}, {food_info_id}, 'single', 'FOOD', '{barcode}%{name}') RETURNING *;"
|
||||||
row = None
|
row = None
|
||||||
try:
|
try:
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
@ -237,6 +306,76 @@ def addItem():
|
|||||||
|
|
||||||
return jsonify({'state': "SUCCESS"})
|
return jsonify({'state': "SUCCESS"})
|
||||||
|
|
||||||
|
@database_api.route("/updateItem", methods=['POST'])
|
||||||
|
def updateItem():
|
||||||
|
def transformValues(values):
|
||||||
|
v = []
|
||||||
|
for value in values:
|
||||||
|
if isinstance(value, dict):
|
||||||
|
v.append(json.dumps(value))
|
||||||
|
elif isinstance(value, list):
|
||||||
|
v.append(main.lst2pgarr(value))
|
||||||
|
else:
|
||||||
|
v.append(value)
|
||||||
|
return v
|
||||||
|
|
||||||
|
def manufactureSQL(keys, item_id, table):
|
||||||
|
if len(keys) > 1:
|
||||||
|
x = f"({', '.join(keys)})"
|
||||||
|
y = f"({', '.join(['%s' for _ in keys])})"
|
||||||
|
else:
|
||||||
|
x = f"{', '.join(keys)}"
|
||||||
|
y = f"{', '.join(['%s' for _ in keys])}"
|
||||||
|
|
||||||
|
sql = f"UPDATE {table} SET {x} = {y} WHERE id={item_id};"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
site_name = session['selected_site']
|
||||||
|
|
||||||
|
item_id = request.get_json()['id']
|
||||||
|
logistics_info_id = request.get_json()['logistics_info_id']
|
||||||
|
food_info_id = request.get_json()['food_info_id']
|
||||||
|
item_info_id = request.get_json()['item_info_id']
|
||||||
|
updated = request.get_json()['updated']
|
||||||
|
item_info = request.get_json()['item_info']
|
||||||
|
food_info = request.get_json()['food_info']
|
||||||
|
logistics_info = request.get_json()['logistics_info']
|
||||||
|
|
||||||
|
database_config = config()
|
||||||
|
|
||||||
|
with psycopg2.connect(**database_config) as conn:
|
||||||
|
try:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
if updated != {}:
|
||||||
|
values = transformValues(updated.values())
|
||||||
|
sql = manufactureSQL(updated.keys(), item_id, f"{site_name}_items")
|
||||||
|
cur.execute(sql, values)
|
||||||
|
if item_info != {}:
|
||||||
|
values = transformValues(item_info.values())
|
||||||
|
sql = manufactureSQL(item_info.keys(), item_info_id, f"{site_name}_item_info")
|
||||||
|
cur.execute(sql, values)
|
||||||
|
if food_info != {}:
|
||||||
|
values = transformValues(food_info.values())
|
||||||
|
sql = manufactureSQL(food_info.keys(), food_info_id, f"{site_name}_food_info")
|
||||||
|
cur.execute(sql, values)
|
||||||
|
if logistics_info != {}:
|
||||||
|
values = transformValues(logistics_info.values())
|
||||||
|
sql = manufactureSQL(logistics_info.keys(), logistics_info_id, f"{site_name}_logistics_info")
|
||||||
|
cur.execute(sql, values)
|
||||||
|
|
||||||
|
cur.execute(f"SELECT barcode FROM {site_name}_items WHERE id={item_id};")
|
||||||
|
barcode = cur.fetchone()[0]
|
||||||
|
print(barcode)
|
||||||
|
main.add_transaction(site_name, barcode, 0, 1, "SYSTEM", "Item data was update!", data=request.get_json())
|
||||||
|
except (Exception, psycopg2.DatabaseError) as error:
|
||||||
|
print(error)
|
||||||
|
conn.rollback()
|
||||||
|
|
||||||
|
return jsonify({"state": "SUCCESS"})
|
||||||
|
|
||||||
|
return jsonify({"status": "FAILED"})
|
||||||
|
|
||||||
@database_api.route("/addGroup")
|
@database_api.route("/addGroup")
|
||||||
def addGroup():
|
def addGroup():
|
||||||
name = str(request.args.get('name', ""))
|
name = str(request.args.get('name', ""))
|
||||||
|
|||||||
26
main.py
26
main.py
@ -248,6 +248,8 @@ def add_food_item(site_name: str, barcode: str, name: str, payload: dict):
|
|||||||
payload["logistics_info"]["primary_location"] = uuid
|
payload["logistics_info"]["primary_location"] = uuid
|
||||||
payload["logistics_info"]["auto_issue_location"] = uuid
|
payload["logistics_info"]["auto_issue_location"] = uuid
|
||||||
|
|
||||||
|
tags = lst2pgarr([])
|
||||||
|
links = json.dumps({})
|
||||||
|
|
||||||
database_config = config()
|
database_config = config()
|
||||||
with psycopg2.connect(**database_config) as conn:
|
with psycopg2.connect(**database_config) as conn:
|
||||||
@ -261,7 +263,7 @@ def add_food_item(site_name: str, barcode: str, name: str, payload: dict):
|
|||||||
if not food_info_id:
|
if not food_info_id:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', {item_info_id}, {logistics_info_id}, {food_info_id}, 'item', 'FOOD', '{barcode}%{name}') RETURNING *;"
|
sqltwo = f"INSERT INTO {site_name}_items(barcode, item_name, tags, links, item_info_id, logistics_info_id, food_info_id, row_type, item_type, search_string) VALUES('{barcode}', '{name}', '{tags}', '{links}', {item_info_id}, {logistics_info_id}, {food_info_id}, 'single', 'FOOD', '{barcode}%{name}') RETURNING *;"
|
||||||
row = None
|
row = None
|
||||||
try:
|
try:
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
@ -398,7 +400,24 @@ payload_food_item = {
|
|||||||
"food_info": {
|
"food_info": {
|
||||||
"food_groups": [],
|
"food_groups": [],
|
||||||
"ingrediants": [],
|
"ingrediants": [],
|
||||||
"nutrients": {},
|
"nutrients": {
|
||||||
|
'serving': '',
|
||||||
|
'serving_unit': '',
|
||||||
|
'calories': '',
|
||||||
|
'calories_unit': 'serving',
|
||||||
|
'proteins': '',
|
||||||
|
'proteins_unit': '',
|
||||||
|
'fats': '',
|
||||||
|
'fats_unit': '',
|
||||||
|
'carbohydrates': '',
|
||||||
|
'carbohydrates_unit': '',
|
||||||
|
'sugars': '',
|
||||||
|
'sugars_unit': '',
|
||||||
|
'sodium': '',
|
||||||
|
'sodium_unit': '',
|
||||||
|
'fibers': '',
|
||||||
|
'fibers_unit': ''
|
||||||
|
},
|
||||||
"expires": False
|
"expires": False
|
||||||
},
|
},
|
||||||
"logistics_info":{
|
"logistics_info":{
|
||||||
@ -426,7 +445,7 @@ def parse_csv(path_to_csv):
|
|||||||
if line[17] != "None":
|
if line[17] != "None":
|
||||||
payload["item_info"]["safety_stock"] = line[17]
|
payload["item_info"]["safety_stock"] = line[17]
|
||||||
qty = float(line[30])
|
qty = float(line[30])
|
||||||
add_food_item(site_name="main", barcode=line[1], name=line[2], qty=qty, payload=payload)
|
add_food_item(site_name="main", barcode=line[1], name=line[2], payload=payload)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -444,3 +463,4 @@ if __name__ == "__main__":
|
|||||||
print(f"{k}: {v}")
|
print(f"{k}: {v}")
|
||||||
"""
|
"""
|
||||||
parse_csv(r"C:\\Users\\jadow\\Documents\\code\\postgresql python\\postgresql-python\\2024-10-02-Pantry.csv")
|
parse_csv(r"C:\\Users\\jadow\\Documents\\code\\postgresql python\\postgresql-python\\2024-10-02-Pantry.csv")
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ WHERE test_items.id=%s;
|
|||||||
22 - linked_items
|
22 - linked_items
|
||||||
23 - shopping_lists
|
23 - shopping_lists
|
||||||
24 - recipes
|
24 - recipes
|
||||||
25 - groups <--
|
25 - groups
|
||||||
26 - packaging
|
26 - packaging
|
||||||
27 - uom
|
27 - uom
|
||||||
28 - cost
|
28 - cost
|
||||||
|
|||||||
@ -1,12 +1,120 @@
|
|||||||
|
async function fetchItem() {
|
||||||
|
const url = new URL('/getItem', window.location.origin);
|
||||||
|
url.searchParams.append('id', item_id);
|
||||||
|
const response = await fetch(url);
|
||||||
|
data = await response.json();
|
||||||
|
item = data.item;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchZones() {
|
||||||
|
const url = new URL('/getZones', window.location.origin);
|
||||||
|
const response = await fetch(url);
|
||||||
|
data = await response.json();
|
||||||
|
zones = data.zones;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchLocations(zone) {
|
||||||
|
const url = new URL('/getLocations', window.location.origin);
|
||||||
|
url.searchParams.append('zone', zone);
|
||||||
|
const response = await fetch(url);
|
||||||
|
data = await response.json();
|
||||||
|
return data.locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function setupLocations(locations, el) {
|
||||||
|
let loc_el = document.getElementById(el)
|
||||||
|
console.log(locations)
|
||||||
|
loc_el.innerHTML = ""
|
||||||
|
|
||||||
|
let option = document.createElement('option')
|
||||||
|
option.value = "undefined"
|
||||||
|
option.innerHTML = "Select Location..."
|
||||||
|
loc_el.appendChild(option)
|
||||||
|
|
||||||
|
for (let i = 0; i < locations.length; i++){
|
||||||
|
let option = document.createElement('option')
|
||||||
|
option.value = locations[i]
|
||||||
|
option.innerHTML = locations[i]
|
||||||
|
loc_el.appendChild(option)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
async function setupZones() {
|
||||||
|
let primary_zone = document.getElementById('primary_zone')
|
||||||
|
|
||||||
|
for (let i = 0; i < zones.length; i++){
|
||||||
|
let option = document.createElement('option')
|
||||||
|
option.value = zones[i]
|
||||||
|
option.innerHTML = zones[i]
|
||||||
|
primary_zone.appendChild(option)
|
||||||
|
};
|
||||||
|
|
||||||
|
let issue_zone = document.getElementById('issue_zone')
|
||||||
|
for (let i = 0; i < zones.length; i++){
|
||||||
|
let option = document.createElement('option')
|
||||||
|
option.value = zones[i]
|
||||||
|
option.innerHTML = zones[i]
|
||||||
|
issue_zone.appendChild(option)
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
async function loadPrimaryLocations() {
|
||||||
|
let primary_zone = document.getElementById('primary_zone').value
|
||||||
|
primary_locations = await fetchLocations(primary_zone)
|
||||||
|
await setupLocations(primary_locations, 'primary_location')
|
||||||
|
};
|
||||||
|
|
||||||
|
async function loadIssueLocations() {
|
||||||
|
let issue_zone = document.getElementById('issue_zone').value
|
||||||
|
issue_locations = await fetchLocations(issue_zone)
|
||||||
|
await setupLocations(issue_locations, 'issue_location')
|
||||||
|
};
|
||||||
|
|
||||||
async function addLink(){
|
async function addLink(){
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
let key = document.getElementById('link_name').value;
|
let key = document.getElementById('link_name').value;
|
||||||
let link = document.getElementById('link').value;
|
let link = document.getElementById('link').value;
|
||||||
links[key] = link;
|
links[key] = link;
|
||||||
console.log(links)
|
console.log(links)
|
||||||
|
links_changed = true;
|
||||||
await propagateLinks()
|
await propagateLinks()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updatePrimaryLocation(){
|
||||||
|
let primary_zone = document.getElementById('primary_zone').value
|
||||||
|
let primary_location = document.getElementById('primary_location').value
|
||||||
|
|
||||||
|
if (primary_location == "undefined"){
|
||||||
|
document.getElementById('primary_location').style = "border-color: red;"
|
||||||
|
} else {
|
||||||
|
document.getElementById('primary_location').style = ""
|
||||||
|
logistics_info['primary_location'] = `${primary_zone}@${primary_location}`
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateIssueLocation(){
|
||||||
|
let issue_zone = document.getElementById('issue_zone').value
|
||||||
|
let issue_location = document.getElementById('issue_location').value
|
||||||
|
|
||||||
|
if (issue_location == "undefined"){
|
||||||
|
document.getElementById('issue_location').style = "border-color: red;"
|
||||||
|
} else {
|
||||||
|
document.getElementById('issue_location').style = ""
|
||||||
|
logistics_info['auto_issue_location'] = `${issue_zone}@${issue_location}`
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateEntryType(){
|
||||||
|
updated['row_type'] = document.getElementById('entry_type').value;
|
||||||
|
console.log(updated)
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateItemType(){
|
||||||
|
updated['item_type'] = document.getElementById('item_type').value;
|
||||||
|
console.log(updated)
|
||||||
|
};
|
||||||
|
|
||||||
function updatePackaging(){
|
function updatePackaging(){
|
||||||
let packaging = document.getElementById('packaging').value;
|
let packaging = document.getElementById('packaging').value;
|
||||||
item_info['packaging'] = packaging;
|
item_info['packaging'] = packaging;
|
||||||
@ -43,3 +151,71 @@ function updateAiPickable(){
|
|||||||
console.log(item_info)
|
console.log(item_info)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updateExpires(){
|
||||||
|
let expires = document.getElementById('expires');
|
||||||
|
food_info['expires'] = expires.checked;
|
||||||
|
console.log(food_info)
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateNutrients(){
|
||||||
|
nutrients = {
|
||||||
|
serving: document.getElementById('serving').value,
|
||||||
|
serving_unit: document.getElementById('serving_unit').value,
|
||||||
|
calories: document.getElementById('calories').value,
|
||||||
|
calories_unit: document.getElementById('calories_unit').value,
|
||||||
|
proteins: document.getElementById('proteins').value,
|
||||||
|
proteins_unit: document.getElementById('proteins_unit').value,
|
||||||
|
fats: document.getElementById('fats').value,
|
||||||
|
fats_unit: document.getElementById('fats_unit').value,
|
||||||
|
carbohydrates: document.getElementById('carbohydrates').value,
|
||||||
|
carbohydrates_unit: document.getElementById('carbohydrates_unit').value,
|
||||||
|
sugars: document.getElementById('sugars').value,
|
||||||
|
sugars_unit: document.getElementById('sugars_unit').value,
|
||||||
|
sodium: document.getElementById('sodium').value,
|
||||||
|
sodium_unit: document.getElementById('sodium_unit').value,
|
||||||
|
fibers: document.getElementById('fibers').value,
|
||||||
|
fibers_unit: document.getElementById('fibers_unit').value
|
||||||
|
};
|
||||||
|
console.log(nutrients)
|
||||||
|
nutrients_changed = true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveItem() {
|
||||||
|
|
||||||
|
// Only add the key, values if something has changed
|
||||||
|
if (food_groups_changed){
|
||||||
|
food_info['food_groups'] = food_groups;
|
||||||
|
};
|
||||||
|
if (tags_changed){
|
||||||
|
updated['tags'] = tags;
|
||||||
|
};
|
||||||
|
if (ingrediants_changed){
|
||||||
|
food_info['ingrediants'] = ingrediants;
|
||||||
|
};
|
||||||
|
if (nutrients_changed){
|
||||||
|
food_info['nutrients'] = nutrients;
|
||||||
|
};
|
||||||
|
if (links_changed){
|
||||||
|
updated['links'] = links;
|
||||||
|
};
|
||||||
|
|
||||||
|
await fetch(`/updateItem`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
id: item_id,
|
||||||
|
logistics_info_id: item[8],
|
||||||
|
food_info_id: item[9],
|
||||||
|
item_info_id: item[7],
|
||||||
|
updated: updated,
|
||||||
|
item_info: item_info,
|
||||||
|
food_info: food_info,
|
||||||
|
logistics_info: logistics_info,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
M.toast({html: "Item has been saved successfully!", classes: "rounded green lighten-4 black-text"});
|
||||||
|
};
|
||||||
|
|||||||
@ -385,7 +385,7 @@
|
|||||||
button_group.style = "margin-bottom: 0px; padding-bottom: 0px;"
|
button_group.style = "margin-bottom: 0px; padding-bottom: 0px;"
|
||||||
button_group.innerHTML = `
|
button_group.innerHTML = `
|
||||||
<div class="col s12" style="align-items: center;">
|
<div class="col s12" style="align-items: center;">
|
||||||
<a href="/getItem?id=${item[0]}"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;">
|
<a href="/item/${item[0]}"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>
|
<i class='material-icons'>edit</i>
|
||||||
</a>
|
</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;">
|
<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;">
|
||||||
|
|||||||
@ -53,121 +53,398 @@
|
|||||||
<li><a href="/groups">Site Groups</a></li>
|
<li><a href="/groups">Site Groups</a></li>
|
||||||
<li><a href="/shopping-lists">Site Shopping Lists</a></li>
|
<li><a href="/shopping-lists">Site Shopping Lists</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<body>
|
<body style="margin-bottom: 80px;">
|
||||||
<div class="container section">
|
<div class="container section">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<div class="col s12">
|
<div class="col s6">
|
||||||
<h3>{{item[2]}}</h3>
|
<a href="#" data-target="slide-out" class="sidenav-trigger hide-on-large-only left btn green lighten-4 black-text btn-flat"><i class="material-icons">menu</i></a>
|
||||||
<h5>Database ID: {{item[0]}}</h5>
|
</div>
|
||||||
<h5>Barcode: {{item[1]}}</h5>
|
<div class="col s6">
|
||||||
</div>
|
<button class="btn btn-flat grey right white-text hide-on-med-and-up show-on-small-only" onclick="saveItem()"><i class="large material-icons">save</i></button>
|
||||||
<div class="s12 m6" style="margin-right: 5px;">
|
</div>
|
||||||
<label for="entry_type">Entry Type</label>
|
<div class="col s12">
|
||||||
<select id="entry_type" class="browser-default" >
|
<h3 id="item_name"></h3>
|
||||||
<option value="" disabled selected>Choose your option</option>
|
</div>
|
||||||
<option value="single">item</option>
|
<div class="col s6">
|
||||||
<option value="linked">linked list</option>
|
<h5 id="database_id"></h5>
|
||||||
</select>
|
</div>
|
||||||
</div>
|
<div class="col s6 right">
|
||||||
<div class="s12 m6">
|
<h5 class="right" id="barcode"></h5>
|
||||||
<label for="item_type">Item Type</label>
|
</div>
|
||||||
<select id="item_type" class="browser-default">
|
<div class="col s12 green lighten-4" style="margin-top: 10px; margin-bottom: 10px; border-radius: 10px;">
|
||||||
<option value="" disabled selected>Choose your option</option>
|
<h5 class="center">Item Types</h5>
|
||||||
<option value="FOOD">Food</option>
|
</div>
|
||||||
<option value="FOOD (PLU)">Food(PLU)</option>
|
<div class="col s12">
|
||||||
<option value="OTHER">Other</option>
|
<div class="card-panel grey z-depth-0 lighten-4">
|
||||||
</select>
|
<span class="black-text">
|
||||||
</div>
|
Here is how you classify the type of item this barcode/id is. There are two types:<br><br>
|
||||||
<!-- Weblinks Input perhaps a modal to add a link or a text input..?-->
|
<b>Entry Type:</b> is how the item is classified across the system.<br>
|
||||||
<div class="divider col s12" style="margin-top: 5px;"></div>
|
<b>Item Type:</b> is more of a subtype for your own filtering and defining.
|
||||||
<div class="col s12">
|
</span>
|
||||||
<div class="row">
|
|
||||||
<div class="col s6" style="padding-top: 10px;">
|
|
||||||
<span style="font-size: 16px;">Links</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6">
|
</div>
|
||||||
<button class="btn btn-small btn-flat right modal-trigger green lighten-4 black-text" data-target="web-modal" style="margin-top: 5px; padding-bottom: 10px;">Add Link</button>
|
<div class="s12 m6" style="margin-right: 5px;">
|
||||||
|
<label for="entry_type">Entry Type</label>
|
||||||
|
<select onchange="updateEntryType()" id="entry_type" class="browser-default" >
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
<option value="single">Single</option>
|
||||||
|
<option value="linked">Linked</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="s12 m6">
|
||||||
|
<label for="item_type">Item Type</label>
|
||||||
|
<select onchange="updateItemType()" id="item_type" class="browser-default">
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
<option value="FOOD">Food</option>
|
||||||
|
<option value="FOOD (PLU)">Food(PLU)</option>
|
||||||
|
<option value="OTHER">Other</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 green lighten-4" style="margin-top: 10px; margin-bottom: 10px; border-radius: 10px;">
|
||||||
|
<h5 class="center">General Tags</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel grey z-depth-0 lighten-4">
|
||||||
|
<span class="black-text">Here is where you can assign this barcode/id general tags to your
|
||||||
|
liking. These can be things that set them apart, group items together, or even little notes
|
||||||
|
to remind yourself what this item is.
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="tags_container" class="col s12 chips">
|
</div>
|
||||||
<!-- This holds open for tags pills -->
|
<div id="tags_container" class="col s12 chips">
|
||||||
</div>
|
<!-- This holds open for tags pills -->
|
||||||
<div class="col s12 p-3">
|
</div>
|
||||||
<div id="weblinks">
|
<!-- Weblinks Input perhaps a modal to add a link or a text input..?-->
|
||||||
|
<div class="divider col s12" style="margin-top: 5px;"></div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12 green lighten-4" style="margin-bottom: 10px; border-radius: 10px;">
|
||||||
|
<h5 class="center">Links</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel grey z-depth-0 lighten-4">
|
||||||
|
<span class="black-text">Here is where you can set links for this barcode/id that
|
||||||
|
might provide you and others paths to understand better what this item is used for.
|
||||||
|
The only rule here is that if you would like for other systems to use a link then you
|
||||||
|
must assign a <b>main</b> link.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col s10">
|
||||||
|
<div id="weblinks">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col s2">
|
||||||
|
<button class="btn btn-small btn-flat right modal-trigger green lighten-4 black-text" data-target="web-modal" style="margin-top: 5px; padding-bottom: 10px;">Add Link</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="divider col s12" style="margin-top: 5px;"></div>
|
||||||
<div class="divider col s12" style="margin-top: 5px;"></div>
|
|
||||||
|
|
||||||
<div class="col s12">
|
<div class="col s12" style="margin-top: 50px;">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<ul class="tabs tabs-fixed-width" id="info_tabs" style="background-color: white;">
|
<ul class="tabs tabs-fixed-width green lighten-4 black-text" id="info_tabs" style="border-radius: 10px 10px 0px 0px">
|
||||||
<li class="tab col s3"><a class="active" href="#item_info">Item Info</a></li>
|
<li class="tab col s3"><a class="active" href="#item_info">Item Info</a></li>
|
||||||
<li class="tab col s3"><a href="#food_info">Food Info</a></li>
|
<li class="tab col s3"><a href="#food_info">Food Info</a></li>
|
||||||
<li class="tab col s3"><a href="#logistics_info">Logistics Info</a></li>
|
<li class="tab col s3"><a href="#logistics_info">Logistics Info</a></li>
|
||||||
<li class="tab col s3 disabled"><a href="#linked_items">Linked Items</a></li>
|
<li class="tab col s3 disabled"><a href="#linked_items">Linked Items</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="item_info" class="col s12">
|
<div id="item_info" class="col s12 grey lighten-5 p-3">
|
||||||
<div class="row" style="gap: 10px; padding-top: 10px;">
|
<div class="row" style="gap: 10px; padding-top: 10px;">
|
||||||
<div class="col s6 m4 input-field outlined item_info_target">
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
<input onchange="updatePackaging()" id="packaging" type="text" placeholder=" " maxlength="32">
|
<h5 class="center">Purchasing/Packaging</h5>
|
||||||
<label for="packaging">Packaging</label>
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
|
<span class="black-text">The following information is used for financial
|
||||||
|
reports and to give quick information to the user how this item is represented
|
||||||
|
logically in the system. <b>Safety Stock</b> and <b>Leadtime</b> is used when using systems that
|
||||||
|
calculate quantites on the fly. <b>AI Pickable</b> sets this item to be used with any
|
||||||
|
Artifical Intelligent systems (TBD).
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 input-field outlined item_info_target">
|
||||||
|
<input onchange="updatePackaging()" id="packaging" type="text" placeholder=" " maxlength="32">
|
||||||
|
<label for="packaging">Packaging</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 input-field outlined item_info_target">
|
||||||
|
<input onchange="updateUOM()" id="uom" type="text" placeholder=" " maxlength="32">
|
||||||
|
<label for="uom">Unit of Measure</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 input-field outlined item_info_target">
|
||||||
|
<input onchange="updateCost()" id="cost" type="number" placeholder=" " maxlength="32">
|
||||||
|
<label for="cost">Cost</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 input-field outlined item_info_target">
|
||||||
|
<input onchange="updateSafetyStock()" id="safety_stock" type="number" placeholder=" " maxlength="32">
|
||||||
|
<label for="safety_stock">Safety Stock</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 input-field outlined item_info_target">
|
||||||
|
<input onchange="updateLeadTimeDays()" id="lead_time_days" type="number" placeholder=" " maxlength="32">
|
||||||
|
<label for="lead_time_days">Leadtime (Days)</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s6 m4 center">
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
<input onclick="updateAiPickable()" id="ai_pickable" type="checkbox" />
|
||||||
|
<span>AI Pickable</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6 m4 input-field outlined item_info_target">
|
<div class="divider col s12" style="margin-top: 10px;"></div>
|
||||||
<input onchange="updateUOM()" id="uom" type="text" placeholder=" " maxlength="32">
|
<div class="row" style="gap: 10px; padding-top: 10px;">
|
||||||
<label for="uom">Unit of Measure</label>
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
</div>
|
<h5 class="center">References</h5>
|
||||||
<div class="col s6 m4 input-field outlined item_info_target">
|
</div>
|
||||||
<input onchange="updateCost()" id="cost" type="number" placeholder=" " maxlength="32">
|
<div class="col s12">
|
||||||
<label for="cost">Cost</label>
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
</div>
|
<span class="black-text">References are where this barcode/id is used in other systems
|
||||||
<div class="col s6 m4 input-field outlined item_info_target">
|
such as Recipes, Shopping Lists, Groups, etc. This will further be expanded on as more
|
||||||
<input onchange="updateSafetyStock()" id="safety_stock" type="number" placeholder=" " maxlength="32">
|
systems are distributed.
|
||||||
<label for="safety_stock">Safety Stock</label>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col s6 m4 input-field outlined item_info_target">
|
</div>
|
||||||
<input onchange="updateLeadTimeDays()" id="lead_time_days" type="number" placeholder=" " maxlength="32">
|
<div class="col s12">
|
||||||
<label for="lead_time_days">Leadtime (Days)</label>
|
<table class="" id="reference_table">
|
||||||
</div>
|
<thead>
|
||||||
<div class="col s6 m4 center">
|
<tr>
|
||||||
<p>
|
<th>Reference Type</th>
|
||||||
<label>
|
<th>Reference Name</th>
|
||||||
<input onclick="updateAiPickable()" id="ai_pickable" type="checkbox" />
|
</tr>
|
||||||
<span>AI Pickable</span>
|
</thead>
|
||||||
</label>
|
<tbody>
|
||||||
</p>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="" id="reference_table">
|
<div id="food_info" class="col s12">
|
||||||
<thead>
|
<div class="row grey lighten-5 p-3" style="gap: 10px; padding-top: 10px;">
|
||||||
<tr>
|
<!-- expiration -->
|
||||||
<th>Reference Type</th>
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
<th>Reference Name</th>
|
<h5 class="center">Expiration</h5>
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
<div class="col s12">
|
||||||
<tbody>
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
</tbody>
|
<span class="black-text">You may want to set up expiration dates for this barcode/id and this is where you
|
||||||
</table>
|
set this information so the system can use that information to send you notifications when
|
||||||
</div>
|
an item has something that will expire.
|
||||||
<div id="food_info" class="col s12">
|
</span>
|
||||||
<div class="row" style="gap: 10px; padding-top: 10px;">
|
</div>
|
||||||
<div id="food_groups_container" class="col s12 chips chips-initial">
|
</div>
|
||||||
<!-- This holds open for food groups pills -->
|
<div class="col s1 m2"></div>
|
||||||
</div>
|
<div class="col s5 m4 input-field outlined item_info_target">
|
||||||
<div id="ingrediants_container" class="col s12 chips">
|
<input id="default_expiry_days" type="number" placeholder=" " maxlength="32" disabled>
|
||||||
<!-- This holds all the ingrediants pills -->
|
<label for="default_expiry_days">Default Expires (Days)</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="nutrients_container" class="col s12">
|
<div class="col s5 m4 center">
|
||||||
<!-- This holds all the nutrients tables -->
|
<p>
|
||||||
|
<label>
|
||||||
|
<input onclick="updateExpires()" id="expires" type="checkbox" />
|
||||||
|
<span>Expires</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m2"></div>
|
||||||
|
|
||||||
|
<!-- Food tags -->
|
||||||
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
|
<h5 class="center">Food Tags</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
|
<span class="black-text">Just like general tags these are tags specific to food items though
|
||||||
|
you can use them entirely to your own wills. These have been seperated by <b>food groups</b> and
|
||||||
|
<b>ingrediants</b>.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="food_groups_container" class="col s12 chips chips-initial">
|
||||||
|
<!-- This holds open for food groups pills -->
|
||||||
|
</div>
|
||||||
|
<div id="ingrediants_container" class="col s12 chips">
|
||||||
|
<!-- This holds all the ingrediants pills -->
|
||||||
|
</div>
|
||||||
|
<div class="divider col s12"></div>
|
||||||
|
<div id="nutrients_container" class="col s12">
|
||||||
|
<div class="row" style="gap: 10px; padding-top: 10px;">
|
||||||
|
<!-- nutrients -->
|
||||||
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
|
<h5 class="center">Nutriments</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
|
<span class="black-text">Self explanitory, this is nutriments for this barcode/id for
|
||||||
|
quick reference for foods. Not really used outside of food items, but if this info is
|
||||||
|
set then other systems will use the info to calculate overall nutriments.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- serving size -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="serving" type="text" placeholder="" name="serving" value="">
|
||||||
|
<label for="serving">Serving</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="serving_unit" type="text" placeholder="" name="serving_unit" value="">
|
||||||
|
<label for="serving_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- calories -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="calories" type="text" placeholder="" name="calories" value="">
|
||||||
|
<label for="calories">Calories</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="calories_unit" type="text" placeholder="" name="calories_unit" value="serving" disabled="">
|
||||||
|
<label for="calories_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Proteins -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="proteins" type="text" placeholder="" name="proteins" value="10.94">
|
||||||
|
<label for="proteins">Proteins</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="proteins_unit" type="text" placeholder="" name="proteins_unit" value="g">
|
||||||
|
<label for="proteins_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Fats -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="fats" type="text" placeholder="" name="fats" value="">
|
||||||
|
<label for="fats">Fats</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="fats_unit" type="text" placeholder="" name="fats_unit" value="">
|
||||||
|
<label for="fats_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Carbohydrates -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="carbohydrates" type="text" placeholder="" name="carbohydrates" value="60.94">
|
||||||
|
<label for="carbohydrates">Carbs</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="carbohydrates_unit" type="text" placeholder="" name="carbohydrates_unit" value="g">
|
||||||
|
<label for="carbohydrates_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Sugars -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="sugars" type="text" placeholder="" name="sugars" value="3.12">
|
||||||
|
<label for="sugars">Sugars</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="sugars_unit" type="text" placeholder="" name="sugars_unit" value="g">
|
||||||
|
<label for="sugars_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Sodium -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="sodium" type="text" placeholder="" name="sodium" value="1.859">
|
||||||
|
<label for="sodium">Sodium</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="sodium_unit" type="text" placeholder="" name="sodium_unit" value="mg">
|
||||||
|
<label for="sodium_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<!-- Fibers -->
|
||||||
|
<div class="col s1 m1"></div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" class="right-align" id="fibers" type="text" placeholder="" name="fibers" value="">
|
||||||
|
<label for="fibers">Fibers</label>
|
||||||
|
</div>
|
||||||
|
<div class="col s5 m2 input-field outlined">
|
||||||
|
<input onchange="updateNutrients()" id="fibers_unit" type="text" placeholder="" name="fibers_unit" value="">
|
||||||
|
<label for="fibers_unit">Unit</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="logistics_info" class="col s12">
|
||||||
|
<div class="row grey lighten-5 p-3" style="gap: 10px; padding-top: 10px;">
|
||||||
|
<div class="col s12 green lighten-4" style="border-radius: 10px;">
|
||||||
|
<h5 class="center">Primary/Auto-Issue</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
|
<span class="black-text">Here is where you will assign this barcode/id's primary zone, primary
|
||||||
|
location, auto-issue zone, and auto-issue location. Essentially the <b>Primary</b> is where
|
||||||
|
the item will be adjusted into by default and the <b>Auto-Issue</b> will be where it is
|
||||||
|
adjusted out of by default. This data is madatory for all items and the admin will have
|
||||||
|
set up defaults for these.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="s12 m6" style="margin-right: 5px;">
|
||||||
|
<label for="primary_zone">Primary Zone</label>
|
||||||
|
<select onchange="loadPrimaryLocations()" id="primary_zone" class="browser-default" >
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="s12 m6" style="margin-right: 5px;">
|
||||||
|
<label for="primary_location">Primary Location</label>
|
||||||
|
<select onchange="updatePrimaryLocation()" id="primary_location" class="browser-default" >
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="s12 m6" style="margin-right: 5px;">
|
||||||
|
<label for="issue_zone">Auto-Issue Zone</label>
|
||||||
|
<select onchange="loadIssueLocations()" id="issue_zone" class="browser-default" >
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="s12 m6" style="margin-right: 5px;">
|
||||||
|
<label for="issue_location">Auto-Issue Location</label>
|
||||||
|
<select onchange="updateIssueLocation()" id="issue_location" class="browser-default" >
|
||||||
|
<option value="" disabled selected>Choose your option</option>
|
||||||
|
<option value="single">Single</option>
|
||||||
|
<option value="linked">Linked</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 green lighten-4" style=" margin-top: 10px; border-radius: 10px;">
|
||||||
|
<h5 class="center">Locations</h5>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card-panel green z-depth-0 lighten-5">
|
||||||
|
<span class="black-text">Here is a general table of where this barcode/id has
|
||||||
|
quantities on hand in the system.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<table class="" id="locations_table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="center">Zone</th>
|
||||||
|
<th class="center">Location</th>
|
||||||
|
<th class="center">QOH</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="linked_items" class="col s12 disabled">Linked Items</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="logistics_info" class="col s12">Logistics Info</div>
|
</div>
|
||||||
<div id="linked_items" class="col s12 disabled">Linked Items</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="web-modal" class="modal">
|
<div id="web-modal" class="modal">
|
||||||
@ -199,22 +476,48 @@
|
|||||||
<button onclick="addLink()" class="waves-effect green lighten-4 btn-flat">Add</button>
|
<button onclick="addLink()" class="waves-effect green lighten-4 btn-flat">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="fixed-action-btn show-on-med-and-up hide-on-small-only">
|
||||||
|
<button class="btn-floating btn-large" onclick="saveItem()">
|
||||||
|
<i class="large material-icons">save</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="{{ url_for('static', filename='itemHandler.js') }}"></script>
|
<script src="{{ url_for('static', filename='itemHandler.js') }}"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var item = {{ item|tojson }};
|
const item_id = {{id|tojson}}
|
||||||
|
let item;
|
||||||
var reference_state = 1
|
var reference_state = 1
|
||||||
let links = {};
|
let zones;
|
||||||
let updated = {};
|
let primary_locations;
|
||||||
let item_info = {};
|
let issue_locations;
|
||||||
let food_info = {};
|
|
||||||
let logistics_info = {};
|
let updated = {}; // updated columns in the item table
|
||||||
|
let item_info = {}; // updated columns in the item_info table
|
||||||
|
let food_info = {}; // updated columns in the food_info table
|
||||||
|
let logistics_info = {}; // updated columns in the logistics_info table
|
||||||
|
|
||||||
let food_groups = [];
|
let food_groups = [];
|
||||||
|
let food_groups_changed = false;
|
||||||
|
|
||||||
let ingrediants = [];
|
let ingrediants = [];
|
||||||
|
let ingrediants_changed = false;
|
||||||
|
|
||||||
let tags = [];
|
let tags = [];
|
||||||
|
let tags_changed = false;
|
||||||
|
|
||||||
|
let links = {};
|
||||||
|
let links_changed = false;
|
||||||
|
|
||||||
|
let nutrients = {};
|
||||||
|
let nutrients_changed = false;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async function() {
|
document.addEventListener('DOMContentLoaded', async function() {
|
||||||
|
await fetchItem()
|
||||||
|
await fetchZones()
|
||||||
|
await setupZones()
|
||||||
|
|
||||||
document.getElementById("title").innerHTML = String(item[2])
|
document.getElementById("title").innerHTML = String(item[2])
|
||||||
|
|
||||||
var elemsSelects = document.querySelectorAll('select');
|
var elemsSelects = document.querySelectorAll('select');
|
||||||
@ -226,53 +529,89 @@
|
|||||||
var elems = document.querySelectorAll('.modal');
|
var elems = document.querySelectorAll('.modal');
|
||||||
var instances = M.Modal.init(elems, {});
|
var instances = M.Modal.init(elems, {});
|
||||||
|
|
||||||
await propagateInfo()
|
M.AutoInit();
|
||||||
|
|
||||||
|
|
||||||
var elem = document.getElementById('food_groups_container');
|
var elem = document.getElementById('food_groups_container');
|
||||||
M.Chips.init(elem, {
|
M.Chips.init(elem, {
|
||||||
placeholder: 'Add Group...',
|
placeholder: 'Add Group...',
|
||||||
secondaryPlaceholder: 'Add Group...',
|
secondaryPlaceholder: 'Add Group...',
|
||||||
onChipDelete: deleteFoodGroup,
|
onChipDelete: deleteChip,
|
||||||
onChipAdd: addFoodGroup,
|
onChipAdd: addChip,
|
||||||
});
|
});
|
||||||
var elem = document.getElementById('ingrediants_container');
|
var elem = document.getElementById('ingrediants_container');
|
||||||
M.Chips.init(elem, {
|
M.Chips.init(elem, {
|
||||||
placeholder: 'Add Ingrediant...',
|
placeholder: 'Add Ingrediant...',
|
||||||
secondaryPlaceholder: 'Add Ingrediant...',
|
secondaryPlaceholder: 'Add Ingrediant...',
|
||||||
onChipDelete: deleteIngrediant,
|
onChipDelete: deleteChip,
|
||||||
onChipAdd: addIngrediant,
|
onChipAdd: addChip,
|
||||||
});
|
});
|
||||||
|
|
||||||
var elem = document.getElementById('tags_container');
|
var elem = document.getElementById('tags_container');
|
||||||
M.Chips.init(elem, {
|
M.Chips.init(elem, {
|
||||||
placeholder: 'Add Tag...',
|
placeholder: 'Add Tag...',
|
||||||
secondaryPlaceholder: 'Add Tag...',
|
secondaryPlaceholder: 'Add Tag...',
|
||||||
onChipDelete: deleteTag,
|
onChipDelete: deleteChip,
|
||||||
onChipAdd: addTag,
|
onChipAdd: addChip,
|
||||||
});
|
});
|
||||||
|
|
||||||
await propagateInfo()
|
await propagateInfo()
|
||||||
//refreshFoodGroups()
|
await propagateLinks()
|
||||||
refreshChips('food_groups_container', food_groups, item[33])
|
await populateLocations()
|
||||||
refreshChips('ingrediants_container', ingrediants, item[34])
|
console.log(updated)
|
||||||
populateReferences(item[23], 'shopping_list')
|
|
||||||
populateReferences(item[24], 'recipe')
|
|
||||||
populateReferences(item[25], 'group')
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
async function propagateInfo(){
|
async function propagateInfo(){
|
||||||
|
document.getElementById('item_name').innerHTML = item[2];
|
||||||
|
document.getElementById('database_id').innerHTML = `Database ID: ${item[0]}`;
|
||||||
|
document.getElementById('barcode').innerHTML = `Barcode: ${item[1]}`;
|
||||||
|
|
||||||
const entryType = document.getElementById('entry_type');
|
const entryType = document.getElementById('entry_type');
|
||||||
entryType.value = item[10];
|
entryType.value = item[10];
|
||||||
const itemType = document.getElementById('item_type');
|
const itemType = document.getElementById('item_type');
|
||||||
itemType.value = item[11];
|
itemType.value = item[11];
|
||||||
await propagateLinks()
|
|
||||||
|
|
||||||
//food_groups = item[33];
|
if (item[6]){
|
||||||
//ingrediants = item[34];
|
links = item[6];
|
||||||
tags = item[5];
|
} else {
|
||||||
|
links = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
refreshChips('food_groups_container', food_groups, item[33])
|
||||||
|
refreshChips('ingrediants_container', ingrediants, item[34])
|
||||||
|
refreshChips('tags_container', tags, item[5])
|
||||||
|
await propagateItemInfo()
|
||||||
|
await propagateNutrients()
|
||||||
|
|
||||||
|
let primary = item[15].split('@')
|
||||||
|
let issue = item[16].split('@')
|
||||||
|
console.log(primary)
|
||||||
|
await setPrimaryLocation(primary[0], primary[1])
|
||||||
|
await setIssueLocation(issue[0], issue[1])
|
||||||
|
|
||||||
|
food_groups_changed = false;
|
||||||
|
ingrediants_changed = false;
|
||||||
|
tags_changed = false;
|
||||||
|
nutrients_changed = false;
|
||||||
|
links_changed = false;
|
||||||
|
|
||||||
|
M.toast({html: "Item has been loaded successfully!", classes: "rounded green lighten-4 black-text flow-text"});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
async function setPrimaryLocation(zone, location){
|
||||||
|
console.log(zone)
|
||||||
|
document.getElementById('primary_zone').value = zone
|
||||||
|
await loadPrimaryLocations()
|
||||||
|
console.log(location)
|
||||||
|
document.getElementById('primary_location').value = location
|
||||||
|
};
|
||||||
|
|
||||||
|
async function setIssueLocation(zone, location){
|
||||||
|
console.log(zone)
|
||||||
|
document.getElementById('issue_zone').value = zone
|
||||||
|
await loadIssueLocations()
|
||||||
|
document.getElementById('issue_location').value = location
|
||||||
};
|
};
|
||||||
|
|
||||||
function refreshChips(elem_id, chips_array, initial_chips){
|
function refreshChips(elem_id, chips_array, initial_chips){
|
||||||
@ -283,42 +622,43 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function addChip(e, chip){
|
||||||
function addFoodGroup(e, chip){
|
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
chipText = chip.textContent.replace('close', '').trim()
|
||||||
console.log(chipText)
|
if (e[0].id == "food_groups_container"){
|
||||||
food_groups.push(chipText)
|
food_groups.push(chipText)
|
||||||
console.log(food_groups)
|
food_groups_changed = true;
|
||||||
}
|
console.log(food_groups)
|
||||||
|
};
|
||||||
function addIngrediant(e, chip){
|
if (e[0].id == "ingrediants_container"){
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
ingrediants.push(chipText)
|
||||||
console.log(chipText)
|
ingrediants_changed = true;
|
||||||
ingrediants.push(chipText)
|
console.log(ingrediants)
|
||||||
console.log(ingrediants)
|
};
|
||||||
}
|
if (e[0].id == "tags_container"){
|
||||||
|
tags.push(chipText)
|
||||||
function addTag(e, chip){
|
tags_changed = true;
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
console.log(tags)
|
||||||
console.log(chipText)
|
};
|
||||||
tags.push(chipText)
|
|
||||||
console.log(tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteFoodGroup(e, chip){
|
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
|
||||||
food_groups = food_groups.filter(chip => chip !== chipText);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function deleteIngrediant(e, chip){
|
function deleteChip(e, chip){
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
chipText = chip.textContent.replace('close', '').trim()
|
||||||
ingrediants = ingrediants.filter(chip => chip !== chipText);
|
if (e[0].id == "food_groups_container"){
|
||||||
}
|
food_groups = food_groups.filter(chip => chip !== chipText);
|
||||||
|
food_groups_changed = true;
|
||||||
function deleteTag(e, chip){
|
console.log(food_groups)
|
||||||
chipText = chip.textContent.replace('close', '').trim()
|
};
|
||||||
tags = tags.filter(chip => chip !== chipText);
|
if (e[0].id == "ingrediants_container"){
|
||||||
}
|
ingrediants = ingrediants.filter(chip => chip !== chipText);
|
||||||
|
ingrediants_changed = true;
|
||||||
|
console.log(ingrediants)
|
||||||
|
};
|
||||||
|
if (e[0].id == "tags_container"){
|
||||||
|
tags = tags.filter(chip => chip !== chipText);
|
||||||
|
tags_changed = true;
|
||||||
|
console.log(tags)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
async function propagateLinks(){
|
async function propagateLinks(){
|
||||||
var element = document.getElementById("weblinks");
|
var element = document.getElementById("weblinks");
|
||||||
@ -335,16 +675,46 @@
|
|||||||
link.href = links[key];
|
link.href = links[key];
|
||||||
element.appendChild(link);
|
element.appendChild(link);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
async function addLink(){
|
async function propagateItemInfo(){
|
||||||
event.preventDefault()
|
document.getElementById('packaging').value = item[26]
|
||||||
let key = document.getElementById('link_name').value;
|
document.getElementById('uom').value = item[27]
|
||||||
let link = document.getElementById('link').value;
|
document.getElementById('cost').value = item[28]
|
||||||
links[key] = link;
|
document.getElementById('safety_stock').value = item[29]
|
||||||
console.log(links)
|
document.getElementById('lead_time_days').value = item[30]
|
||||||
await propagateLinks()
|
// ai_pickable
|
||||||
}
|
document.getElementById('ai_pickable').checked = item[31];
|
||||||
|
document.getElementById('expires').checked = item[36];
|
||||||
|
|
||||||
|
populateReferences(item[23], 'shopping_list')
|
||||||
|
populateReferences(item[24], 'recipe')
|
||||||
|
populateReferences(item[25], 'group')
|
||||||
|
};
|
||||||
|
|
||||||
|
async function propagateNutrients(){
|
||||||
|
if (item[35]){
|
||||||
|
nutrients = item[35];
|
||||||
|
} else {
|
||||||
|
nutrients = {};
|
||||||
|
};
|
||||||
|
document.getElementById('serving').value = nutrients['serving']
|
||||||
|
document.getElementById('serving_unit').value = nutrients['serving_unit']
|
||||||
|
document.getElementById('calories').value = nutrients['calories']
|
||||||
|
document.getElementById('calories_unit').value = nutrients['calories_unit']
|
||||||
|
document.getElementById('proteins').value = nutrients['proteins']
|
||||||
|
document.getElementById('proteins_unit').value = nutrients['proteins_unit']
|
||||||
|
document.getElementById('fats').value = nutrients['fats']
|
||||||
|
document.getElementById('fats_unit').value = nutrients['fats_unit']
|
||||||
|
document.getElementById('carbohydrates').value = nutrients['carbohydrates']
|
||||||
|
document.getElementById('carbohydrates_unit').value = nutrients['carbohydrates_unit']
|
||||||
|
document.getElementById('sugars').value = nutrients['sugars']
|
||||||
|
document.getElementById('sugars_unit').value = nutrients['sugars_unit']
|
||||||
|
document.getElementById('sodium').value = nutrients['sodium']
|
||||||
|
document.getElementById('sodium_unit').value = nutrients['sodium_unit']
|
||||||
|
document.getElementById('fibers').value = nutrients['fibers']
|
||||||
|
document.getElementById('fibers_unit').value = nutrients['fibers_unit']
|
||||||
|
};
|
||||||
|
|
||||||
function populateReferences(references, reference_type){
|
function populateReferences(references, reference_type){
|
||||||
var table = document.getElementById("reference_table")
|
var table = document.getElementById("reference_table")
|
||||||
@ -361,8 +731,42 @@
|
|||||||
row.style = "background-color: gainsboro;"
|
row.style = "background-color: gainsboro;"
|
||||||
}
|
}
|
||||||
reference_state++
|
reference_state++
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
|
async function populateLocations(){
|
||||||
|
var table = document.getElementById("locations_table")
|
||||||
|
console.log(item[18])
|
||||||
|
|
||||||
|
let colorstate = 1;
|
||||||
|
|
||||||
|
for (let key in item[18]){
|
||||||
|
console.log(item[18][key])
|
||||||
|
|
||||||
|
this_location = key.split("@")
|
||||||
|
qty = item[18][key]
|
||||||
|
|
||||||
|
var row = table.insertRow();
|
||||||
|
|
||||||
|
var row_type = row.insertCell();
|
||||||
|
var row_name = row.insertCell();
|
||||||
|
var row_qty = row.insertCell();
|
||||||
|
|
||||||
|
row_type.classList.add("center")
|
||||||
|
row_name.classList.add("center")
|
||||||
|
row_qty.classList.add("center")
|
||||||
|
|
||||||
|
|
||||||
|
row_type.innerHTML = this_location[0]
|
||||||
|
row_name.innerHTML = this_location[1]
|
||||||
|
row_qty.innerHTML = qty
|
||||||
|
|
||||||
|
if ((colorstate % 2) == 0){
|
||||||
|
row.style = "background-color: gainsboro;"
|
||||||
|
}
|
||||||
|
colorstate++
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
255
templates/items/transactions.html
Normal file
255
templates/items/transactions.html
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8" />
|
||||||
|
<title id="title"></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>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
header, main, footer, body {
|
||||||
|
padding-left: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width : 992px) {
|
||||||
|
header, main, footer, body {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dropdown-disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5; /* or your desired degree of transparency */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<ul id='dropdown1' class='dropdown-content'>
|
||||||
|
{% for site in sites %}
|
||||||
|
<li><button class="btn transparent black-text z-depth-0" onclick="changeSite('{{ site }}')">{{site}}</button></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<ul id="slide-out" class="sidenav sidenav-fixed green lighten-4" style="width: 250px;">
|
||||||
|
<li>
|
||||||
|
<div class="user-view">
|
||||||
|
<!-- <div class="background">
|
||||||
|
<img src="images/office.jpg">
|
||||||
|
</div> -->
|
||||||
|
<!-- <a href="#user"><img class="circle" src="images/yuna.jpg"></a> -->
|
||||||
|
<a href="#name"><span class="black-text name">John Doe</span></a>
|
||||||
|
<a href="#email"><span class="black-text email">jdoe@example.com</span></a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><a class="dropdown-trigger dropdown-disabled" data-target="dropdown1">Current Site > {{current_site}}<i class="material-icons right">arrow_drop_down</i></a></li>
|
||||||
|
<li><div class="divider grey darken-1" style="margin-left: 5px; margin-right: 10px;"></div></li>
|
||||||
|
<li><a href="/items">Site Items</a></li>
|
||||||
|
<li><a href="/groups">Site Groups</a></li>
|
||||||
|
<li><a href="/shopping-lists">Site Shopping Lists</a></li>
|
||||||
|
</ul>
|
||||||
|
<body style="margin-bottom: 80px;">
|
||||||
|
<div class="container section">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col s6">
|
||||||
|
<a href="#" data-target="slide-out" class="sidenav-trigger hide-on-large-only left btn green lighten-4 black-text btn-flat"><i class="material-icons">menu</i></a>
|
||||||
|
</div>
|
||||||
|
<div class="col s6">
|
||||||
|
<button class="btn btn-flat grey right white-text hide-on-med-and-up show-on-small-only" onclick="saveItem()"><i class="large material-icons">save</i></button>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<table id="transaction_table">
|
||||||
|
<thead>
|
||||||
|
</thead>
|
||||||
|
<tbody id="table_body">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 center" id="pagination_list">
|
||||||
|
<ul class="pagination">
|
||||||
|
<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 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 modal-trigger" href="#modal1"><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>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
const item_id = {{id|tojson}}
|
||||||
|
let current_page = 1
|
||||||
|
let end_page;
|
||||||
|
let limit = 50
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', async function() {
|
||||||
|
await fetchTransactions();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetchTransactions(){
|
||||||
|
console.log(current_page)
|
||||||
|
if (current_page === 1){
|
||||||
|
document.getElementById('back').classList.add("disabled")
|
||||||
|
document.getElementById('back').classList.remove("waves-effect")
|
||||||
|
document.getElementById('first').classList.add("disabled")
|
||||||
|
document.getElementById('first').classList.remove("waves-effect")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
document.getElementById('back').classList.remove("disabled")
|
||||||
|
document.getElementById('back').classList.add("waves-effect")
|
||||||
|
document.getElementById('first').classList.remove("disabled")
|
||||||
|
document.getElementById('first').classList.add("waves-effect")
|
||||||
|
};
|
||||||
|
const url = new URL('/getTransactions', window.location.origin);
|
||||||
|
url.searchParams.append('id', item_id);
|
||||||
|
url.searchParams.append('page', current_page);
|
||||||
|
url.searchParams.append('limit', limit);
|
||||||
|
await fetch(url)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
|
||||||
|
end_page = parseInt(data.end)
|
||||||
|
if (current_page === end_page){
|
||||||
|
document.getElementById('forward').classList.add("disabled")
|
||||||
|
document.getElementById('forward').classList.remove("waves-effect")
|
||||||
|
document.getElementById('last').classList.add("disabled")
|
||||||
|
document.getElementById('last').classList.remove("waves-effect")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
document.getElementById('forward').classList.remove("disabled")
|
||||||
|
document.getElementById('forward').classList.add("waves-effect")
|
||||||
|
document.getElementById('last').classList.remove("disabled")
|
||||||
|
document.getElementById('last').classList.add("waves-effect")
|
||||||
|
};
|
||||||
|
console.log(data)
|
||||||
|
var table = document.getElementById("transaction_table")
|
||||||
|
while (table.rows.length > 0) {
|
||||||
|
table.deleteRow(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = table.createTHead();
|
||||||
|
const row = header.insertRow(0);
|
||||||
|
|
||||||
|
var header_id = row.insertCell();
|
||||||
|
header_id.classList.add('center')
|
||||||
|
header_id.classList.add('hide-on-med-and-down')
|
||||||
|
var header_stamp = row.insertCell();
|
||||||
|
header_stamp.classList.add('center')
|
||||||
|
var header_barcode = row.insertCell();
|
||||||
|
header_barcode.classList.add('center')
|
||||||
|
var header_name = row.insertCell();
|
||||||
|
header_name.classList.add('center')
|
||||||
|
header_name.classList.add('hide-on-med-and-down')
|
||||||
|
var header_type = row.insertCell();
|
||||||
|
header_type.classList.add('center')
|
||||||
|
header_type.classList.add('hide-on-small-only')
|
||||||
|
var header_qty = row.insertCell();
|
||||||
|
header_qty.classList.add('center')
|
||||||
|
var header_desc = row.insertCell();
|
||||||
|
header_desc.classList.add('center')
|
||||||
|
header_desc.classList.add('hide-on-med-and-down')
|
||||||
|
var header_user = row.insertCell();
|
||||||
|
header_user.classList.add('center')
|
||||||
|
header_user.classList.add('hide-on-med-and-down')
|
||||||
|
|
||||||
|
header_id.innerHTML = `<b>Database ID</b>`;
|
||||||
|
header_stamp.innerHTML = `<b>Timestamp</b>`;
|
||||||
|
header_barcode.innerHTML = `<b>Barcode</b>`;
|
||||||
|
header_name.innerHTML = `<b>Name</b>`;
|
||||||
|
header_type.innerHTML = `<b>Type</b>`;
|
||||||
|
header_qty.innerHTML = `<b>Qty</b>`;
|
||||||
|
header_desc.innerHTML = `<b>Description</b>`;
|
||||||
|
header_user.innerHTML = `<b>UserID</b>`;
|
||||||
|
|
||||||
|
let colorstate = 1;
|
||||||
|
data.transactions.forEach(transaction => {
|
||||||
|
console.log(transaction)
|
||||||
|
table.c
|
||||||
|
var row = table.insertRow();
|
||||||
|
|
||||||
|
var row_id = row.insertCell();
|
||||||
|
row_id.classList.add('center')
|
||||||
|
row_id.classList.add('hide-on-med-and-down')
|
||||||
|
var row_stamp = row.insertCell();
|
||||||
|
row_stamp.classList.add('center')
|
||||||
|
var row_barcode = row.insertCell();
|
||||||
|
row_barcode.classList.add('center')
|
||||||
|
var row_name = row.insertCell();
|
||||||
|
row_name.classList.add('hide-on-med-and-down')
|
||||||
|
row_name.classList.add('center')
|
||||||
|
var row_type = row.insertCell();
|
||||||
|
row_type.classList.add('center')
|
||||||
|
row_type.classList.add('hide-on-small-only')
|
||||||
|
var row_qty = row.insertCell();
|
||||||
|
row_qty.classList.add('center')
|
||||||
|
var row_desc = row.insertCell();
|
||||||
|
row_desc.classList.add('center')
|
||||||
|
row_desc.classList.add('hide-on-med-and-down')
|
||||||
|
var row_user = row.insertCell();
|
||||||
|
row_user.classList.add('center')
|
||||||
|
row_user.classList.add('hide-on-med-and-down')
|
||||||
|
|
||||||
|
row_id.innerHTML = transaction[0];
|
||||||
|
row_stamp.innerHTML = transaction[1];
|
||||||
|
row_barcode.innerHTML = transaction[3];
|
||||||
|
row_name.innerHTML = transaction[4];
|
||||||
|
row_type.innerHTML = transaction[5];
|
||||||
|
row_qty.innerHTML = transaction[6];
|
||||||
|
row_desc.innerHTML = transaction[7];
|
||||||
|
row_user.innerHTML = transaction[8];
|
||||||
|
|
||||||
|
|
||||||
|
if ((colorstate % 2) == 0){
|
||||||
|
row.classList.add('green')
|
||||||
|
row.classList.add('lighten-5')
|
||||||
|
}
|
||||||
|
colorstate++
|
||||||
|
});
|
||||||
|
document.getElementById("current_page").innerHTML = `${String(current_page)} / ${String(end_page)}`
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('forward').addEventListener('click', async () =>{
|
||||||
|
if (!(document.getElementById("forward").classList.contains("disabled"))){
|
||||||
|
current_page++
|
||||||
|
await fetchTransactions();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('back').addEventListener('click', async () =>{
|
||||||
|
if (!(document.getElementById("back").classList.contains("disabled"))){
|
||||||
|
current_page--
|
||||||
|
await fetchTransactions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('last').addEventListener('click', async () =>{
|
||||||
|
if(!(document.getElementById("last").classList.contains("disabled"))){
|
||||||
|
current_page = end_page
|
||||||
|
await fetchTransactions();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('first').addEventListener('click', async () =>{
|
||||||
|
if (!(document.getElementById("first").classList.contains("disabled"))){
|
||||||
|
current_page = 1
|
||||||
|
await fetchTransactions();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
12
webserver.py
12
webserver.py
@ -9,6 +9,18 @@ def group(id):
|
|||||||
sites = config.sites_config()
|
sites = config.sites_config()
|
||||||
return render_template("groups/group.html", id=id, current_site=session['selected_site'], sites=sites['sites'])
|
return render_template("groups/group.html", id=id, current_site=session['selected_site'], sites=sites['sites'])
|
||||||
|
|
||||||
|
@app.route("/transactions/<id>")
|
||||||
|
def transactions(id):
|
||||||
|
sites = config.sites_config()
|
||||||
|
return render_template("items/transactions.html", id=id, current_site=session['selected_site'], sites=sites['sites'])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/item/<id>")
|
||||||
|
def item(id):
|
||||||
|
sites = config.sites_config()
|
||||||
|
return render_template("items/item.html", id=id, current_site=session['selected_site'], sites=sites['sites'])
|
||||||
|
|
||||||
|
|
||||||
@app.route("/workshop")
|
@app.route("/workshop")
|
||||||
def workshop():
|
def workshop():
|
||||||
sites = config.sites_config()
|
sites = config.sites_config()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user