another large clean up of code, all POSTs are now using make_response() and returning json OR are for a form that flask handles with rendering direct html. Where there is a POST with json response, the jscript now calls CheckForJobs() to show it in the F/E. Removed several debugs. Fixed up undocumented BUG where import datetime was wrong, and prefix/suffix also to offer directories near the date of an image. Removed unused routes for clearing messages
This commit is contained in:
6
TODO
6
TODO
@@ -1,10 +1,4 @@
|
||||
### GENERAL
|
||||
* should be using jsonify to return real json to my API calls, e.g:
|
||||
use make_response( jsonify (... ) )
|
||||
-- [TODO] all POSTs should follow new status behaviour (unless its a form POST, as that immediately renders the form in flask and will show the Status)
|
||||
all GETs stay as is for now (as they expect a html reply, not data, and then html is base.html+ and it handles the status)
|
||||
-- [TODO] find persons needs an array returned - test this, also viewlist
|
||||
|
||||
* delete files should behave like /move_files (stay on same page) as well as the status messages above
|
||||
|
||||
* all routes should be consistent naming conventions (with or without _ )
|
||||
|
||||
4
ai.py
4
ai.py
@@ -1,6 +1,6 @@
|
||||
from wtforms import SubmitField, StringField, HiddenField, validators, Form
|
||||
from flask_wtf import FlaskForm
|
||||
from flask import request, render_template, redirect
|
||||
from flask import request, render_template, redirect, make_response
|
||||
from main import db, app, ma
|
||||
from sqlalchemy import Sequence
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
@@ -124,4 +124,4 @@ def get_face_from_image(face_id):
|
||||
img_bytearray = img_bytearray.getvalue()
|
||||
face_img = base64.b64encode(img_bytearray)
|
||||
face_img = str(face_img)[2:-1]
|
||||
return face_img
|
||||
return make_response( face_img )
|
||||
|
||||
33
files.py
33
files.py
@@ -15,7 +15,7 @@ import numpy
|
||||
import cv2
|
||||
import time
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import pytz
|
||||
from flask_login import login_required, current_user
|
||||
from states import States, PA_UserState
|
||||
@@ -366,16 +366,6 @@ def GetEntries( OPT ):
|
||||
UpdatePref( pref, OPT )
|
||||
return entries
|
||||
|
||||
################################################################################
|
||||
# /clear_jm_msg -> with a dismissable error (ie. anything not success, that is
|
||||
# not showing duplicates (so rare errors) - allow them to be dismissed
|
||||
################################################################################
|
||||
@app.route("/clear_jm_msg/<id>", methods=["POST"])
|
||||
@login_required
|
||||
def clear_jm_msg(id):
|
||||
ClearJM_Message(id)
|
||||
return redirect( url_for("main_page") )
|
||||
|
||||
@app.route("/ChangeFileOpts", methods=["POST"])
|
||||
@login_required
|
||||
def ChangeFileOpts():
|
||||
@@ -500,7 +490,7 @@ def fix_dups():
|
||||
rows = db.engine.execute( "select e1.id as id1, f1.hash, d1.rel_path as rel_path1, d1.eid as did1, e1.name as fname1, p1.id as path1, p1.type_id as path_type1, e2.id as id2, d2.rel_path as rel_path2, d2.eid as did2, e2.name as fname2, p2.id as path2, p2.type_id as path_type2 from entry e1, file f1, dir d1, entry_dir_link edl1, path_dir_link pdl1, path p1, entry e2, file f2, dir d2, entry_dir_link edl2, path_dir_link pdl2, path p2 where e1.id = f1.eid and e2.id = f2.eid and d1.eid = edl1.dir_eid and edl1.entry_id = e1.id and edl2.dir_eid = d2.eid and edl2.entry_id = e2.id and p1.type_id != (select id from path_type where name = 'Bin') and p1.id = pdl1.path_id and pdl1.dir_eid = d1.eid and p2.type_id != (select id from path_type where name = 'Bin') and p2.id = pdl2.path_id and pdl2.dir_eid = d2.eid and f1.hash = f2.hash and e1.id != e2.id and f1.size_mb = f2.size_mb order by path1, rel_path1, fname1");
|
||||
|
||||
if rows.returns_rows == False:
|
||||
SetFELog(f"Err, no dups - should now clear the FE 'danger' message?", "warning")
|
||||
SetFELog(f"Err, No more duplicates? Old link followed, or something is wrong!", "warning")
|
||||
return redirect("/")
|
||||
|
||||
if 'pagesize' not in request.form:
|
||||
@@ -653,7 +643,7 @@ def viewlist():
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.orig_ptype==OPT.orig_ptype,PA_UserState.view_eid==OPT.view_eid).first()
|
||||
UpdatePref( pref, OPT )
|
||||
|
||||
return resp
|
||||
return make_response( resp )
|
||||
|
||||
################################################################################
|
||||
# /view/id -> grabs data from DB and views it (GET)
|
||||
@@ -785,7 +775,7 @@ def _jinja2_filter_parentpath(path):
|
||||
|
||||
###############################################################################
|
||||
# route to allow the Move Dialog Box to pass a date (YYYYMMDD) and returns a
|
||||
# json? list of existing dir names that could be near it in time. Starting
|
||||
# json list of existing dir names that could be near it in time. Starting
|
||||
# simple, by using YYYYMM-1, YYYYMM, YYYYMM+1 dirs
|
||||
###############################################################################
|
||||
@app.route("/getexistingpaths/<dt>", methods=["POST"])
|
||||
@@ -795,13 +785,15 @@ def GetExistingPathsAsDiv(dt):
|
||||
dirs_arr=[]
|
||||
for delta in range(-7, 8):
|
||||
try:
|
||||
new_dtime=datetime.datetime.strptime(dt, "%Y%m%d") + datetime.timedelta(days=delta)
|
||||
new_dtime=datetime.strptime(dt, "%Y%m%d") + timedelta(days=delta)
|
||||
except:
|
||||
# this is not a date, so we cant work out possible dirs, just
|
||||
# return an empty set
|
||||
return "[]"
|
||||
return make_response( '[]' )
|
||||
new_dt=new_dtime.strftime('%Y%m%d')
|
||||
# find dirs named with this date
|
||||
dirs_arr+=Dir.query.distinct(Dir.rel_path).filter(Dir.rel_path.ilike('%'+new_dt+'%')).all();
|
||||
# find dirs with non-dirs (files) with this date
|
||||
dirs_arr+=Dir.query.distinct(Dir.rel_path).join(EntryDirLink).join(Entry).filter(Entry.type_id!=dir_ft.id).filter(Entry.name.ilike('%'+new_dt+'%')).all()
|
||||
|
||||
# remove duplicates from array
|
||||
@@ -811,12 +803,17 @@ def GetExistingPathsAsDiv(dt):
|
||||
ret='[ '
|
||||
first_dir=1
|
||||
for dir in dirs:
|
||||
print(dir)
|
||||
# this can occur if there is a file with this date name in the top-levle of the path, its legit, but only really happens in DEV
|
||||
# regardless, it cant be used for a existpath button in the F/E, ignore it
|
||||
if dir.rel_path == '':
|
||||
continue
|
||||
if not first_dir:
|
||||
ret +=", "
|
||||
bits=dir.rel_path.split('-')
|
||||
|
||||
ret+= '{ '
|
||||
ret+= '"prefix":"' + bits[0] + '", '
|
||||
ret+= '"prefix":"' + bits[0] + '-", '
|
||||
if len(bits)>1:
|
||||
ret+= '"suffix":"' + bits[1] + '"'
|
||||
else:
|
||||
@@ -824,4 +821,4 @@ def GetExistingPathsAsDiv(dt):
|
||||
ret+= ' } '
|
||||
first_dir=0
|
||||
ret+= ' ]'
|
||||
return ret
|
||||
return make_response( ret )
|
||||
|
||||
@@ -21,14 +21,15 @@ function GetSelnAsData()
|
||||
return to_del
|
||||
}
|
||||
|
||||
// use an ajax POST to force an AI scan on the selected images
|
||||
// use an ajax POST to force an AI scan on the selected image(s)
|
||||
function RunAIOnSeln(person)
|
||||
{
|
||||
post_data = GetSelnAsData()
|
||||
post_data += '&person='+person.replace('ai-','')
|
||||
$.ajax({ type: 'POST', data: post_data, url: '/run_ai_on', success: function(data){ window.location='/'; return false; } })
|
||||
$.ajax({ type: 'POST', data: post_data, url: '/run_ai_on', success: function(data){ CheckForJobs() } })
|
||||
}
|
||||
|
||||
// code to change the associated image/icon when the move to selection box (import or storage paths) is changed
|
||||
function change_rp_sel()
|
||||
{
|
||||
icon_url = $('option:selected', '#rp_sel').attr('icon_url')
|
||||
@@ -37,6 +38,8 @@ function change_rp_sel()
|
||||
$('#move_path_type').val( $('option:selected', '#rp_sel').attr('path_type') )
|
||||
}
|
||||
|
||||
// POST to see if there are any other existing directories named around this date
|
||||
// (if so display them as options for a move)
|
||||
function GetExistingDirsAsDiv( dt, divname )
|
||||
{
|
||||
$.ajax({
|
||||
@@ -46,7 +49,7 @@ function GetExistingDirsAsDiv( dt, divname )
|
||||
dirs = JSON.parse(data)
|
||||
s=''
|
||||
dirs.forEach( function(item, index) {
|
||||
s+= '<button class="btn btn-outline-primary" type="button" onClick="$(\'#prefix\').val(\''+item.prefix+'\'); $(\'#suffix\').val(\''+item.suffix+'\');return false;">'+item.prefix+'/'+item.suffix+'</button>'
|
||||
s+= '<button class="btn btn-outline-primary" type="button" onClick="$(\'#prefix\').val(\''+item.prefix+'\'); $(\'#suffix\').val(\''+item.suffix+'\');return false;">'+item.prefix+item.suffix+'</button>'
|
||||
} )
|
||||
if( s == '' )
|
||||
$('#existing').html('')
|
||||
@@ -59,12 +62,12 @@ function GetExistingDirsAsDiv( dt, divname )
|
||||
// used to remove the highlighted item(s) -- effectively removing them from view/selection so continued 'Moves' can occur
|
||||
function MoveSubmit()
|
||||
{
|
||||
// remove the images being moved
|
||||
// remove the images being moved (so UI immediately 'sees' the move)
|
||||
$("[name^=eid-]").each( function() { $('#'+$(this).attr('value')).remove() } )
|
||||
// reorder the images via ecnt again, so highlighting can work
|
||||
// reorder the images via ecnt again, so future highlighting can work
|
||||
document.mf_id=0; $('.figure').each( function() { $(this).attr('ecnt', document.mf_id ); document.mf_id++ } )
|
||||
$('#dbox').modal('hide')
|
||||
$.ajax({ type: 'POST', data: $('#mv_fm').serialize(), url: '/move_files', success: function(data){ CheckForJobs(); return false; } })
|
||||
$.ajax({ type: 'POST', data: $('#mv_fm').serialize(), url: '/move_files', success: function(data) { CheckForJobs() } })
|
||||
}
|
||||
|
||||
// show the DBox for a move file, includes all thumbnails of selected files to move
|
||||
@@ -134,13 +137,13 @@ function DelDBox(del_or_undel)
|
||||
if( del_or_undel == "Delete" )
|
||||
div+=`
|
||||
'/delete_files',
|
||||
success: function(data){ window.location='/'; return false; } })" class="btn btn-outline-danger col-2">Ok</button>
|
||||
success: function(data){ window.location='/'; CheckForJobs() } })" class="btn btn-outline-danger col-2">Ok</button>
|
||||
</div>
|
||||
`
|
||||
else
|
||||
div+=`
|
||||
'/restore_files',
|
||||
success: function(data){ window.location='/'; return false; } })" class="btn btn-outline-success col-2">Ok</button>
|
||||
success: function(data){ window.location='/'; CheckForJobs() } })" class="btn btn-outline-success col-2">Ok</button>
|
||||
</div>
|
||||
`
|
||||
$('#dbox-content').html(div)
|
||||
|
||||
@@ -287,6 +287,7 @@ function OverrideForceMatch( person_id, key )
|
||||
$('#dbox').modal('hide')
|
||||
$('#faces').prop('checked',true)
|
||||
DrawImg()
|
||||
CheckForJobs()
|
||||
}
|
||||
} )
|
||||
}
|
||||
@@ -320,6 +321,7 @@ function AddRefimgTo( person_id, key, search )
|
||||
$('#dbox').modal('hide')
|
||||
$('#faces').prop('checked',true)
|
||||
DrawImg()
|
||||
CheckForJobs()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -374,6 +376,7 @@ function RemoveOverrideForceMatch(face_pos)
|
||||
delete objs[current].faces[face_pos].override
|
||||
$('#dbox').modal('hide')
|
||||
DrawImg()
|
||||
CheckForJobs()
|
||||
return false
|
||||
}
|
||||
} )
|
||||
@@ -388,6 +391,7 @@ function RemoveOverrideNoMatch(face_pos, type_id)
|
||||
delete objs[current].faces[face_pos].override
|
||||
$('#dbox').modal('hide')
|
||||
DrawImg()
|
||||
CheckForJobs()
|
||||
return false
|
||||
}
|
||||
} )
|
||||
@@ -407,6 +411,7 @@ function AddNoMatchOverride(type_id, face_id, face_pos, type_id)
|
||||
$('#dbox').modal('hide')
|
||||
$('#faces').prop('checked',true)
|
||||
DrawImg()
|
||||
CheckForJobs()
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
15
job.py
15
job.py
@@ -297,6 +297,7 @@ def joblog_search():
|
||||
for ent in ent_cursor:
|
||||
jobs_cursor=db.engine.execute( f"select l.log, j.id, j.name, j.state, l.log_date from joblog l, job j where l.job_id = j.id and l.log ilike '%%{ent[0]}%%' order by l.log_date")
|
||||
|
||||
print("HERE")
|
||||
# turn DB output into json and return it to the f/e
|
||||
ret='[ '
|
||||
first_job=1
|
||||
@@ -312,7 +313,7 @@ def joblog_search():
|
||||
ret+= '}'
|
||||
first_job=0
|
||||
ret+= ' ]'
|
||||
return ret
|
||||
return make_response( ret )
|
||||
|
||||
|
||||
###############################################################################
|
||||
@@ -331,18 +332,6 @@ def CheckForJobs():
|
||||
sts.append( { 'id': msg.id, 'message': u+msg.message, 'level': msg.level, 'job_id': msg.job_id, 'persistent': msg.persistent, 'cant_close': msg.cant_close } )
|
||||
return make_response( jsonify( num_active_jobs=num, sts=sts ) )
|
||||
|
||||
###############################################################################
|
||||
# / -> POST -> looks for pa_job_manager status to F/E jobs and sends json of
|
||||
# them back to F/E (called form internal/js/jobs.js:CheckForJobs()
|
||||
################################################################################
|
||||
@app.route("/clearmsgforjob/<id>", methods=["POST"])
|
||||
@login_required
|
||||
def ClearMessageForJob(id):
|
||||
PA_JobManager_Message.query.filter(PA_JobManager_Message.job_id==id).delete()
|
||||
db.session.commit()
|
||||
# no real need for this response, as if it succeeded/failed the F/E ignores it
|
||||
return make_response( jsonify( status="success" ) )
|
||||
|
||||
###############################################################################
|
||||
# / -> POST -> looks for pa_job_manager status to F/E jobs and sends json of
|
||||
# them back to F/E (called form internal/js/jobs.js:CheckForJobs()
|
||||
|
||||
11
person.py
11
person.py
@@ -249,11 +249,12 @@ def person(id):
|
||||
@app.route("/add_refimg", methods=["POST"])
|
||||
@login_required
|
||||
def add_refimg():
|
||||
# now save into the DB
|
||||
person = Person.query.get(request.form['person_id']);
|
||||
if not person:
|
||||
raise Exception("could not find person to add reference image too!")
|
||||
try:
|
||||
# now save into the DB
|
||||
person = Person.query.get(request.form['person_id']);
|
||||
if not person:
|
||||
raise Exception("could not find person to add reference image too!")
|
||||
|
||||
# save the actual uploaded image to reference_images/
|
||||
f=request.files['refimg_file']
|
||||
fname=secure_filename(f.filename)
|
||||
@@ -285,7 +286,7 @@ def find_persons(who):
|
||||
resp[p.id]['firstname']=p.firstname
|
||||
resp[p.id]['surname']=p.surname
|
||||
|
||||
return resp
|
||||
return make_response( resp )
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -100,7 +100,6 @@ def settings():
|
||||
from job import SetFELog
|
||||
s = Settings.query.one()
|
||||
if 'submit' in request.form:
|
||||
SetFELog("Successfully Updated Settings" )
|
||||
s.import_path = request.form['import_path']
|
||||
s.storage_path = request.form['storage_path']
|
||||
s.recycle_bin_path = request.form['recycle_bin_path']
|
||||
@@ -118,7 +117,8 @@ def settings():
|
||||
s.scheduled_bin_cleanup = request.form['scheduled_bin_cleanup']
|
||||
s.bin_cleanup_file_age = request.form['bin_cleanup_file_age']
|
||||
s.job_archive_age = request.form['job_archive_age']
|
||||
db.session.commit()
|
||||
SetFELog("Successfully Updated Settings" )
|
||||
db.session.commit()
|
||||
return redirect( url_for( 'settings' ) )
|
||||
except SQLAlchemyError as e:
|
||||
SetFELog( f"<b>Failed to modify Setting:</b> {e.orig}", "danger" )
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
function ResetPageSize()
|
||||
{
|
||||
console.log( $("#pagesize").val() )
|
||||
$("#psform").submit()
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
orig_face_{{f.id}}.orig_w = {{f.face_right}}*1.05 - {{f.face_left}}*.95
|
||||
orig_face_{{f.id}}.orig_h = {{f.face_bottom}}*1.05 - {{f.face_top}}*.95
|
||||
|
||||
//console.log( orig_face_{{f.id}} )
|
||||
|
||||
// when the document is ready, then DrawRefimg
|
||||
$(function() { DrawUnmatchedFace( fig_{{f.id}}, im_{{f.id}}, c_{{f.id}}, orig_face_{{f.id}} ) });
|
||||
</script>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
{% block script_content %}
|
||||
<script>
|
||||
<!-- browsers can put the fakepath in for security, remove it -->
|
||||
function DoMagic() {
|
||||
str=$("#new_file_chooser").val()
|
||||
console.log(str)
|
||||
|
||||
Reference in New Issue
Block a user