Added progress bar to create set

This commit is contained in:
FrederikBaerentsen 2024-04-18 22:11:44 +02:00
parent 5a45034d9b
commit e835b8f3a2
4 changed files with 351 additions and 217 deletions

184
app.py
View File

@ -1,5 +1,7 @@
from flask import Flask, request, redirect, jsonify, render_template, Response,url_for from flask import Flask, request, redirect, jsonify, render_template, Response,url_for
import json import json
from flask_socketio import SocketIO
from threading import Thread
from pprint import pprint as pp from pprint import pprint as pp
from pathlib import Path from pathlib import Path
import time,random,string,sqlite3 import time,random,string,sqlite3
@ -10,9 +12,30 @@ import requests # request img from web
import shutil # save img locally import shutil # save img locally
app = Flask(__name__) app = Flask(__name__)
socketio = SocketIO(app)
count = 0
@app.route('/favicon.ico') @app.route('/favicon.ico')
# SocketIO event handler for client connection
@socketio.on('connect', namespace='/progress')
def test_connect():
print('Client connected')
# SocketIO event handler for client disconnection
@socketio.on('disconnect', namespace='/progress')
def test_disconnect():
print('Client disconnected')
# SocketIO event handler for starting the task
@socketio.on('start_task', namespace='/progress')
def start_task(data):
input_value = data.get('inputField')
print(input_value)
# Start the task in a separate thread to avoid blocking the server
thread = Thread(target=new_set, args=(input_value,))
thread.start()
@app.route('/delete/<tmp>',methods=['POST', 'GET']) @app.route('/delete/<tmp>',methods=['POST', 'GET'])
def delete(tmp): def delete(tmp):
@ -32,22 +55,22 @@ def delete(tmp):
conn.close() conn.close()
return redirect('/') return redirect('/')
@app.route('/create',methods=['GET', 'POST']) def new_set(set_num):
def create(): global count
conn = sqlite3.connect('app.db') ###### total count ####
cursor = conn.cursor() # 1 for set
count = 0 # 1 for set image
if request.method == 'GET':
print('get')
if request.method == 'POST': total_parts = 2
set_num = request.form['inputField']
set_num = set_num
# add_duplicate = request.form.get('addDuplicate', False) == 'true' # add_duplicate = request.form.get('addDuplicate', False) == 'true'
# Do something with the input value and the checkbox value # Do something with the input value and the checkbox value
# print("Input value:", set_num) # print("Input value:", set_num)
# print("Add duplicate:", add_duplicate) # print("Add duplicate:", add_duplicate)
# You can perform any further processing or redirect to another page # You can perform any further processing or redirect to another page
conn = sqlite3.connect('app.db')
cursor = conn.cursor()
if '-' not in set_num: if '-' not in set_num:
set_num = set_num + '-1' set_num = set_num + '-1'
@ -62,13 +85,13 @@ def create():
response = '' response = ''
try: try:
response = json.loads(rebrick.lego.get_set(set_num).read()) response = json.loads(rebrick.lego.get_set(set_num).read())
except Exception as e: except Exception as e:
print(e.code) #print(e.code)
if e.code == 404: if e.code == 404:
return render_template('create.html',error=set_num) return render_template('create.html',error=set_num)
count+=1 count+=1
cursor.execute('''INSERT INTO sets ( cursor.execute('''INSERT INTO sets (
set_num, set_num,
name, name,
@ -91,23 +114,25 @@ def create():
# Get set image. Saved under ./static/sets/xxx-x.jpg # Get set image. Saved under ./static/sets/xxx-x.jpg
set_img_url = response["set_img_url"] set_img_url = response["set_img_url"]
print('Saving set image:',end='') #print('Saving set image:',end='')
res = requests.get(set_img_url, stream = True) res = requests.get(set_img_url, stream = True)
count+=1 count+=1
if res.status_code == 200: if res.status_code == 200:
with open("./static/sets/"+set_num+".jpg",'wb') as f: with open("./static/sets/"+set_num+".jpg",'wb') as f:
shutil.copyfileobj(res.raw, f) shutil.copyfileobj(res.raw, f)
print(' OK') #print(' OK')
else: else:
print('Image Couldn\'t be retrieved for set ' + set_num) #print('Image Couldn\'t be retrieved for set ' + set_num)
logging.error('set_img_url: ' + set_num) logging.error('set_img_url: ' + set_num)
print(' ERROR') #print(' ERROR')
# Get inventory and add to SQL # Get inventory and add to SQL
response = json.loads(rebrick.lego.get_set_elements(set_num,page_size=20000).read()) response = json.loads(rebrick.lego.get_set_elements(set_num,page_size=20000).read())
count+=1 count+=1
total_parts += len(response['results'])
socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
for i in response['results']: for i in response['results']:
# Get part image. Saved under ./static/parts/xxxx.jpg # Get part image. Saved under ./static/parts/xxxx.jpg
part_img_url = i['part']['part_img_url'] part_img_url = i['part']['part_img_url']
@ -119,13 +144,13 @@ def create():
if match: if match:
part_img_url_id = match.group(1) part_img_url_id = match.group(1)
print("Part number:", part_img_url_id) #print("Part number:", part_img_url_id)
else: else:
print("Part number not found in the URL.") #print("Part number not found in the URL.")
print(">>> " + part_img_url) print(">>> " + part_img_url)
except Exception as e: except Exception as e:
print("Part number not found in the URL.") #print("Part number not found in the URL.")
print(">>> " + str(part_img_url)) #print(">>> " + str(part_img_url))
print(str(e)) print(str(e))
@ -151,32 +176,33 @@ def create():
if not Path("./static/parts/"+part_img_url_id+".jpg").is_file(): if not Path("./static/parts/"+part_img_url_id+".jpg").is_file():
print('Saving part image:',end='') #print('Saving part image:',end='')
if part_img_url is not None: if part_img_url is not None:
res = requests.get(part_img_url, stream = True) res = requests.get(part_img_url, stream = True)
count+=1 count+=1
socketio.emit('update_progress', {'progress': count}, namespace='/progress')
if res.status_code == 200: if res.status_code == 200:
with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f: with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f:
shutil.copyfileobj(res.raw, f) shutil.copyfileobj(res.raw, f)
print(' OK') #print(' OK')
else: else:
print('Image Couldn\'t be retrieved for set ' + part_img_url_id) #print('Image Couldn\'t be retrieved for set ' + part_img_url_id)
logging.error('part_img_url: ' + part_img_url_id) logging.error('part_img_url: ' + part_img_url_id)
print(' ERROR') #print(' ERROR')
else: else:
print('Part url is None') #print('Part url is None')
print(i) print(i)
else:
print(part_img_url_id + '.jpg exists!')
conn.commit() conn.commit()
# Get minifigs # Get minifigs
print('Savings minifigs') #print('Savings minifigs')
tmp_set_num = set_num tmp_set_num = set_num
response = json.loads(rebrick.lego.get_set_minifigs(set_num).read()) response = json.loads(rebrick.lego.get_set_minifigs(set_num).read())
count+=1 count+=1
print(response) socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
#print(response)
for i in response['results']: for i in response['results']:
@ -184,20 +210,20 @@ def create():
set_img_url = i["set_img_url"] set_img_url = i["set_img_url"]
set_num = i['set_num'] set_num = i['set_num']
print('Saving set image:',end='') #print('Saving set image:',end='')
if not Path("./static/minifigs/"+set_num+".jpg").is_file(): if not Path("./static/minifigs/"+set_num+".jpg").is_file():
res = requests.get(set_img_url, stream = True) res = requests.get(set_img_url, stream = True)
count+=1 count+=1
socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
if res.status_code == 200: if res.status_code == 200:
with open("./static/minifigs/"+set_num+".jpg",'wb') as f: with open("./static/minifigs/"+set_num+".jpg",'wb') as f:
shutil.copyfileobj(res.raw, f) shutil.copyfileobj(res.raw, f)
print(' OK') #print(' OK')
else: else:
print('Image Couldn\'t be retrieved for set ' + set_num) #print('Image Couldn\'t be retrieved for set ' + set_num)
logging.error('set_img_url: ' + set_num) logging.error('set_img_url: ' + set_num)
print(' ERROR') #print(' ERROR')
else:
print(set_img_url + '.jpg exists!')
cursor.execute('''INSERT INTO minifigures ( cursor.execute('''INSERT INTO minifigures (
fig_num, fig_num,
@ -213,7 +239,7 @@ def create():
# Get minifigs inventory # Get minifigs inventory
response_minifigs = json.loads(rebrick.lego.get_minifig_elements(i['set_num']).read()) response_minifigs = json.loads(rebrick.lego.get_minifig_elements(i['set_num']).read())
count+=1 count+=1
socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
for i in response_minifigs['results']: for i in response_minifigs['results']:
# Get part image. Saved under ./static/parts/xxxx.jpg # Get part image. Saved under ./static/parts/xxxx.jpg
@ -225,25 +251,26 @@ def create():
if match: if match:
part_img_url_id = match.group(1) part_img_url_id = match.group(1)
print("Part number:", part_img_url_id) #print("Part number:", part_img_url_id)
if not Path("./static/parts/"+part_img_url_id+".jpg").is_file(): if not Path("./static/parts/"+part_img_url_id+".jpg").is_file():
print('Saving part image:',end='') #print('Saving part image:',end='')
res = requests.get(part_img_url, stream = True) res = requests.get(part_img_url, stream = True)
count+=1 count+=1
socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
if res.status_code == 200: if res.status_code == 200:
with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f: with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f:
shutil.copyfileobj(res.raw, f) shutil.copyfileobj(res.raw, f)
print(' OK') #print(' OK')
else: else:
print('Image Couldn\'t be retrieved for set ' + part_img_url_id) #print('Image Couldn\'t be retrieved for set ' + part_img_url_id)
logging.error('part_img_url: ' + part_img_url_id) logging.error('part_img_url: ' + part_img_url_id)
print(' ERROR') #print(' ERROR')
else: else:
print(part_img_url_id + '.jpg exists!') print(part_img_url_id + '.jpg exists!')
except Exception as e: except Exception as e:
print("Part number not found in the URL.") #print("Part number not found in the URL.")
print(">>> " + str(part_img_url)) #print(">>> " + str(part_img_url))
print(str(e)) print(str(e))
cursor.execute('''INSERT INTO inventory ( cursor.execute('''INSERT INTO inventory (
@ -265,10 +292,20 @@ def create():
conn.commit() conn.commit()
conn.close() conn.close()
print(count) count = total_parts
return redirect('/') socketio.emit('update_progress', {'progress': int(count/total_parts*100)}, namespace='/progress')
count = 0
socketio.emit('task_completed', namespace='/progress')
@app.route('/create',methods=['POST','GET'])
def create():
global count
conn.close()
print('Count: ' + str(count)) print('Count: ' + str(count))
@ -293,7 +330,7 @@ def index():
results = cursor.fetchall() results = cursor.fetchall()
set_list = [list(i) for i in results] set_list = [list(i) for i in results]
print(set_list) #print(set_list)
for i in set_list: for i in set_list:
try: try:
i[3] = theme_file[theme_file[:, 0] == str(i[3])][0][1] i[3] = theme_file[theme_file[:, 0] == str(i[3])][0][1]
@ -305,6 +342,57 @@ def index():
conn.close() conn.close()
return render_template('index.html',set_list=set_list,themes_list=theme_file) return render_template('index.html',set_list=set_list,themes_list=theme_file)
if request.method == 'POST':
set_num = request.form.get('set_num')
u_id = request.form.get('u_id')
minif = request.form.get('minif')
scheck = request.form.get('scheck')
scol = request.form.get('scol')
conn = sqlite3.connect('app.db')
cursor = conn.cursor()
if minif != None:
if minif == 'true':
val = 1
else:
val = 0
cursor.execute('''UPDATE sets
SET mini_col = ?
WHERE set_num = ? AND
u_id = ?''',
(val, set_num, u_id))
conn.commit()
if scheck != None:
if scheck == 'true':
val = 1
else:
val = 0
cursor.execute('''UPDATE sets
SET set_check = ?
WHERE set_num = ? AND
u_id = ?''',
(val, set_num, u_id))
conn.commit()
if scol != None:
if scol == 'true':
val = 1
else:
val = 0
cursor.execute('''UPDATE sets
SET set_col = ?
WHERE set_num = ? AND
u_id = ?''',
(val, set_num, u_id))
conn.commit()
cursor.close()
conn.close()
return ('', 204)
@app.route('/<tmp>/<u_id>', methods=['GET', 'POST']) @app.route('/<tmp>/<u_id>', methods=['GET', 'POST'])
def inventory(tmp,u_id): def inventory(tmp,u_id):
@ -557,4 +645,4 @@ def save_number(tmp):
return Response(status=204) return Response(status=204)
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, port=3333) socketio.run(app.run(host='0.0.0.0', debug=True, port=3333))

View File

@ -44,7 +44,7 @@ cursor.execute('''CREATE TABLE IF NOT EXISTS sets (
last_modified_dt TEXT, last_modified_dt TEXT,
mini_col BOOLEAN, mini_col BOOLEAN,
set_check BOOLEAN, set_check BOOLEAN,
set_col, BOOLEAN, set_col BOOLEAN,
u_id TEXT u_id TEXT
)''') )''')

View File

@ -7,6 +7,8 @@
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css"> href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.3.1/socket.io.js" crossorigin="anonymous"></script>
</head> </head>
<body> <body>
<nav class="navbar is-dark is-fixed-top" role="navigation" aria-label="main navigation"> <nav class="navbar is-dark is-fixed-top" role="navigation" aria-label="main navigation">
@ -36,15 +38,17 @@
<input class="input" type="text" id="inputField" name="inputField"> <input class="input" type="text" id="inputField" name="inputField">
</div> </div>
</div> </div>
<progress id="progress-bar" class="progress is-large is-primary" value="0" max="100">
</progress>
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<button class="button is-primary" type="submit">Submit</button> <button id="submitButton" class="button is-primary" type="submit">Submit</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</section> </section>
{% if error is defined %} {% if error is defined %}
<button class="js-modal-trigger" data-target="modal-js-example" id="modal-js"> <button class="js-modal-trigger" data-target="modal-js-example" id="modal-js">
</button> </button>
@ -73,13 +77,33 @@
</footer> </footer>
</div> </div>
</div> </div>
</body> </body>
<script> <script>
var socket = io.connect('http://' + document.domain + ':' + location.port + '/progress');
// Event listener for receiving progress updates
socket.on('update_progress', function(msg) {
var progress = msg.progress;
// document.getElementById("progress-bar").style.width = progress + "%";
document.getElementById("progress-bar").value = progress;
document.getElementById("progress-bar").innerText = progress + "%";
});
// Event listener for the form submission
document.getElementById("createForm").addEventListener("submit", function(event) {
event.preventDefault(); // Prevent default form submission
var inputField = document.getElementById("inputField").value;
socket.emit('start_task', { inputField: inputField }); // Emit socket event with inputField value
});
// Event listener for the 'task_completed' event
socket.on('task_completed', function() {
// Redirect to '/'
window.location.href = '/';
});
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
window.onload = function () { window.onload = function () {

View File

@ -204,7 +204,7 @@
<div class="columns" style=""> <div class="columns" style="">
<div class="column is-half" style=""> <div class="column is-half" style="">
<figure class="image is-4by3"> <figure class="image is-4by3">
<a href="/{{ i[0] }}/{{ i[12] }}"> <a href="/{{ i[0] }}/{{ i[11] }}">
<img style='height: 100%; width: 100%; object-fit: contain' src="/static/sets/{{ i[0] }}.jpg" alt="Image"> <img style='height: 100%; width: 100%; object-fit: contain' src="/static/sets/{{ i[0] }}.jpg" alt="Image">
</a> </a>
</figure> </figure>
@ -214,32 +214,54 @@
<div class="is-size-7"> <div class="is-size-7">
<label class="checkbox" > <label class="checkbox" >
<input type="hidden" id="set_num" value="{{ i[0] }}"> <input type="hidden" id="set_num" value="{{ i[0] }}">
<input type="hidden" id="u_id" value="{{ i[11] }}">
{% if i[8] == 0 %}
<input class="s_fig" id="s_fig" type="checkbox" />
{% else %}
<input class="s_fig" id="s_fig" type="checkbox" checked /> <input class="s_fig" id="s_fig" type="checkbox" checked />
{% endif %}
<!-- {{ i[8] }}<br>
{{ i[9] }}<br>
{{ i[10] }}<br> -->
Minifigs Collected Minifigs Collected
</label> </label>
<br> <br>
<label class="checkbox" > <label class="checkbox" >
<input type="hidden" id="set_num" value="{{ i['set_num'] }}"> <input type="hidden" id="set_num" value="{{ i[0] }}">
<input type="hidden" id="u_id" value="{{ i[11] }}">
{% if i[9] == 0 %}
<input class="s_check" id="s_check" type="checkbox" />
{% else %}
<input class="s_check" id="s_check" type="checkbox" checked /> <input class="s_check" id="s_check" type="checkbox" checked />
{% endif %}
Set is checked Set is checked
</label> </label>
<br> <br>
<label class="checkbox" > <label class="checkbox" >
<input type="hidden" id="set_num" value="{{ i['set_num'] }}"> <input type="hidden" id="set_num" value="{{ i[0] }}">
<input type="hidden" id="u_id" value="{{ i[11] }}">
{% if i[10] == 0 %}
<input class="s_col" id="s_col" type="checkbox" />
{% else %}
<input class="s_col" id="s_col" type="checkbox" checked /> <input class="s_col" id="s_col" type="checkbox" checked />
{% endif %}
Set is collected and boxed Set is collected and boxed
</label> </label>
<br> <br>
<fieldset disabled>
<label class="checkbox" > <label class="checkbox" >
<input type="checkbox" class="s_com" onclick="return false;"/> Set is missing pieces <input type="checkbox" class="s_com" onclick="return false;"/> Set is missing pieces
</label> </label>
</fieldset>
</div> </div>
</div> </div>
</div> </div>
<footer class="card-footer" style=""> <footer class="card-footer" style="">
<p class="card-footer-item"> <p class="card-footer-item">
<span> <span>
<span class="is-size-7">{{ i[12] }}</span> <span class="is-size-7">{{ i[11] }}</span>
</span> </span>
</p> </p>
@ -367,7 +389,7 @@
$("body").on("change", "#s_fig", function (event) { $("body").on("change", "#s_fig", function (event) {
minif = $(this).prop('checked'); minif = $(this).prop('checked');
set_num = $(this).siblings('#set_num').val(); set_num = $(this).siblings('#set_num').val();
index = $(this).siblings('#index').val(); u_id = $(this).siblings('#u_id').val();
$.ajax({ $.ajax({
url: '/', url: '/',
@ -375,7 +397,7 @@
data: { data: {
'set_num': set_num, 'set_num': set_num,
'minif': minif, 'minif': minif,
'index': index 'u_id': u_id
} }
}); });
}); });
@ -383,7 +405,7 @@
$("body").on("change", "#s_check", function (event) { $("body").on("change", "#s_check", function (event) {
scheck = $(this).prop('checked'); scheck = $(this).prop('checked');
set_num = $(this).siblings('#set_num').val(); set_num = $(this).siblings('#set_num').val();
index = $(this).siblings('#index').val(); u_id = $(this).siblings('#u_id').val();
$.ajax({ $.ajax({
url: '/', url: '/',
@ -391,7 +413,7 @@
data: { data: {
'set_num': set_num, 'set_num': set_num,
'scheck': scheck, 'scheck': scheck,
'index': index 'u_id': u_id
} }
}); });
}); });
@ -399,7 +421,7 @@
$("body").on("change", "#s_col", function (event) { $("body").on("change", "#s_col", function (event) {
scol = $(this).prop('checked'); scol = $(this).prop('checked');
set_num = $(this).siblings('#set_num').val(); set_num = $(this).siblings('#set_num').val();
index = $(this).siblings('#index').val(); u_id = $(this).siblings('#u_id').val();
$.ajax({ $.ajax({
url: '/', url: '/',
@ -407,7 +429,7 @@
data: { data: {
'set_num': set_num, 'set_num': set_num,
'scol': scol, 'scol': scol,
'index': index 'u_id': u_id
} }
}); });
}); });