Huge change, removed Status class and all "alert" messages are now shown as BS toast() and are via the DB and handled async in the F/E in jscript via Ajax. Fixed BUG-113 where toasts() were repeating. Removed many of the explicit alert messages (other than errors) and hooked {New|Finish}Job to consistently send messages to the F/E. Other messages (F/E without a job, like save settings) now use this model as well. Finally converted most of the older POST responses to formal json

This commit is contained in:
2023-01-11 13:50:05 +11:00
parent 2be2c504b2
commit a29cbb143c
15 changed files with 162 additions and 217 deletions

View File

@@ -1,17 +1,16 @@
from wtforms import SubmitField, StringField, HiddenField, validators, Form
from flask_wtf import FlaskForm
from flask import request, render_template, redirect, url_for
from flask import request, render_template, redirect, url_for, make_response, jsonify
from main import db, app, ma
from settings import Settings, AIModel
from sqlalchemy import Sequence
from sqlalchemy.exc import SQLAlchemyError
from status import st, Status
from flask_login import login_required, current_user
from werkzeug.utils import secure_filename
from shared import GenFace, GenThumb, PA
from face import Face, FaceRefimgLink, FaceOverrideType, FaceNoMatchOverride, FaceForceMatchOverride
from path import Path, PathType
from job import JobExtra, NewJob
from job import JobExtra, NewJob, SetFELog
import os
import time
@@ -98,7 +97,7 @@ def AddRefimgToPerson( filename, person ):
print( f"Failed to delete tmp file for refimg addition: {e}" )
if not face_locn:
st.SetMessage( f"<b>Failed to find face in Refimg:</b>" )
SetFELog( f"<b>Failed to find face in Refimg:</b>", "danger" )
raise Exception("Could not find face in uploaded reference image" )
return
refimg.face_top = face_locn[0]
@@ -111,11 +110,11 @@ def AddRefimgToPerson( filename, person ):
db.session.add(person)
db.session.add(refimg)
db.session.commit()
st.SetMessage( f"Associated new Refimg ({refimg.fname}) with person: {person.tag}" )
SetFELog( f"Associated new Refimg ({refimg.fname}) with person: {person.tag}" )
except SQLAlchemyError as e:
st.SetMessage( f"<b>Failed to add Refimg:</b>&nbsp;{e.orig}", "danger" )
SetFELog( f"<b>Failed to add Refimg:</b>&nbsp;{e.orig}", "danger" )
except Exception as e:
st.SetMessage( f"<b>Failed to modify Refimg:</b>&nbsp;{e}", "danger" )
SetFELog( f"<b>Failed to modify Refimg:</b>&nbsp;{e}", "danger" )
return
################################################################################
@@ -171,10 +170,10 @@ def new_person():
try:
db.session.add(person)
db.session.commit()
st.SetMessage( "Created new Person ({})".format(person.tag) )
SetFELog( f"Created new Person ({person.tag})" )
return redirect( url_for( 'person', id=person.id) )
except SQLAlchemyError as e:
st.SetMessage( f"<b>Failed to add Person:</b>&nbsp;{e.orig}", "danger" )
SetFELog( f"<b>Failed to add Person:</b>&nbsp;{e.orig}", "danger" )
return redirect( url_for( '/persons') )
else:
return render_template("person.html", person=None, form=form, page_title=page_title )
@@ -186,10 +185,8 @@ def match_with_create_person():
# add this fname (of temp refimg) to person
fname=TempRefimgFile( request.form['refimg_data'], p.tag )
AddRefimgToPerson( fname, p )
resp={}
resp['who']=p.tag
resp['distance']='0.0'
return resp
SetFELog( f"Created person: {p.tag}" )
return make_response( jsonify( who=p.tag, distance='0.0' ) )
################################################################################
# /person/<id> -> GET/POST(save or delete) -> shows/edits/delets a single person
@@ -204,7 +201,7 @@ def person(id):
try:
person = Person.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted Person: ({})".format( person.tag ) )
SetFELog( f"Successfully deleted Person: ({person.tag})" )
# do linkages by hand, or one day replace with delete cascade in the DB defintions
db.session.execute( f"delete from face_refimg_link frl where refimg_id in ( select refimg_id from person_refimg_link where person_id = {id} )" )
db.session.execute( f"delete from person_refimg_link where person_id = {id}" )
@@ -225,23 +222,23 @@ def person(id):
# delete the "match" between a face found in a file and this ref img
FaceRefimgLink.query.filter(FaceRefimgLink.refimg_id==deld[0].id).delete()
Refimg.query.filter(Refimg.id==deld[0].id).delete()
st.SetMessage( f"Successfully Updated Person: removed reference image {deld[0].fname}" )
SetFELog( f"Successfully Updated Person: removed reference image {deld[0].fname}" )
else:
st.SetMessage("Successfully Updated Person: (From: {}, {}, {})".format(person.tag, person.firstname, person.surname) )
s=f"Successfully Updated Person: (From: {person.tag}, {person.firstname}, {person.surname})"
person.tag = request.form['tag']
person.surname = request.form['surname']
person.firstname = request.form['firstname']
st.AppendMessage(" To: ({}, {}, {})".format(person.tag, person.firstname, person.surname) )
SetFELog( f"{s} To: ({person.tag}, {person.firstname}, {person.surname})" )
db.session.add(person)
db.session.commit()
return redirect( url_for( 'person', id=person.id) )
except SQLAlchemyError as e:
st.SetMessage( f"<b>Failed to modify Person:</b>&nbsp;{e}", "danger" )
SetFELog( f"<b>Failed to modify Person:</b>&nbsp;{e}", "danger" )
return redirect( url_for( 'persons' ) )
else:
person = Person.query.get(id)
if not person:
st.SetMessage( f"No such person with id: {id}", "danger" )
SetFELog( f"No such person with id: {id}", "danger" )
return redirect("/")
form = PersonForm(request.values, obj=person)
return render_template("person.html", person=person, form=form, page_title = page_title)
@@ -266,7 +263,7 @@ def add_refimg():
fname = f"/tmp/{fname}"
f.save( fname )
except Exception as e:
st.SetMessage( f"<b>Failed to load reference image:</b>&nbsp;{e}", "danger" )
SetFELog( f"<b>Failed to load reference image:</b>&nbsp;{e}", "danger" )
AddRefimgToPerson( fname, person )
return redirect( url_for( 'person', id=person.id) )
@@ -297,7 +294,6 @@ def find_persons(who):
@app.route("/add_refimg_to_person", methods=["POST"])
@login_required
def add_refimg_to_person():
resp={}
f = Face.query.get( request.form['face_id'] )
p = Person.query.get( request.form['person_id'] )
@@ -310,19 +306,15 @@ def add_refimg_to_person():
ptype=PathType.query.filter(PathType.name=='Import').first()
jex.append( JobExtra( name=f"person", value="all" ) )
jex.append( JobExtra( name=f"path_type", value=ptype.id ) )
job=NewJob( "run_ai_on_path", 0, None, jex )
st.SetMessage( f"Created&nbsp;<a href=/job/{job.id}>Job #{job.id}</a>&nbsp;to Look for face(s) in import path(s)")
job=NewJob( name="run_ai_on_path", num_files=0, wait_for=None, jex=jex, desc="Look for face(s) in import path(s)" )
jex=[]
ptype=PathType.query.filter(PathType.name=='Storage').first()
jex.append( JobExtra( name=f"person", value="all" ) )
jex.append( JobExtra( name=f"path_type", value=ptype.id ) )
job=NewJob( "run_ai_on_path", 0, None, jex )
st.SetMessage( f"Created&nbsp;<a href=/job/{job.id}>Job #{job.id}</a>&nbsp;to Look for face(s) in storage path(s)")
job=NewJob( name="run_ai_on_path", num_files=0, wait_for=None, jex=jex, desc="Look for face(s) in storage path(s)" )
resp['who']=p.tag
resp['distance']='0.0'
return resp
return make_response( jsonify( who=p.tag, distance='0.0' ) )
################################################################################
# /add_force_match_override -> POST
@@ -349,13 +341,11 @@ def add_force_match_override():
jex.append( JobExtra( name="face_id", value=f.id ) )
jex.append( JobExtra( name="person_id", value=p.id ) )
# dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E
NewJob( "metadata", 0, None, jex )
NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for adding forced match" )
print( f"Placing an override match with face_id {face_id}, for person: {p.tag}" )
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override to person_tag
resp={}
resp['person_tag']=p.tag
return resp
return make_response( jsonify( person_tag=p.tag ) )
################################################################################
# /remove_force_match_override -> POST
@@ -379,11 +369,10 @@ def remove_force_match_override():
jex.append( JobExtra( name="face_id", value=face_id ) )
jex.append( JobExtra( name="person_id", value=p.id ) )
# dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E
NewJob( "metadata", 0, None, jex )
NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for removing forced match" )
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override
resp={}
return resp
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override (data is not used)
return make_response( jsonify( person_tag=p.tag ) )
################################################################################
# /remove_no_match_override -> POST
@@ -403,11 +392,10 @@ def remove_no_match_override():
jex.append( JobExtra( name="face_id", value=face_id ) )
jex.append( JobExtra( name="type_id", value=type_id ) )
# dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E
NewJob( "metadata", 0, None, jex )
NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for removing forced non-match" )
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override
resp={}
return resp
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override (data is not used)
return make_response( jsonify( face_id=face_id ) )
################################################################################
@@ -435,10 +423,8 @@ def add_no_match_override():
jex.append( JobExtra( name="face_id", value=f.id ) )
jex.append( JobExtra( name="type_id", value=t.id ) )
# dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E
NewJob( "metadata", 0, None, jex )
NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for adding forced non-match" )
print( f"Placing an override of NO Match for face_id {face_id}" )
# this will reply to the Ajax / POST, and cause the page to re-draw with new face override to person_tag
resp={}
resp['type']=t.name
return resp
return make_response( jsonify( type=t.name ) )