diff --git a/TODO b/TODO index cc6f236..7840495 100644 --- a/TODO +++ b/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 _ ) diff --git a/ai.py b/ai.py index 416f625..773a9aa 100644 --- a/ai.py +++ b/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 ) diff --git a/files.py b/files.py index 385aaa0..39ca4f7 100644 --- a/files.py +++ b/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/", 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/
", 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 ) diff --git a/internal/js/files_support.js b/internal/js/files_support.js index 445875a..18e890e 100644 --- a/internal/js/files_support.js +++ b/internal/js/files_support.js @@ -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+= '' + s+= '' } ) 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 + success: function(data){ window.location='/'; CheckForJobs() } })" class="btn btn-outline-danger col-2">Ok ` else div+=` '/restore_files', - success: function(data){ window.location='/'; return false; } })" class="btn btn-outline-success col-2">Ok + success: function(data){ window.location='/'; CheckForJobs() } })" class="btn btn-outline-success col-2">Ok ` $('#dbox-content').html(div) diff --git a/internal/js/view_support.js b/internal/js/view_support.js index fd602eb..6c9d59e 100644 --- a/internal/js/view_support.js +++ b/internal/js/view_support.js @@ -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() } } ) } diff --git a/job.py b/job.py index d03cb26..6d9035a 100644 --- a/job.py +++ b/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/", 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() diff --git a/person.py b/person.py index e6b0212..a9a0f3e 100644 --- a/person.py +++ b/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 ) ################################################################################ diff --git a/settings.py b/settings.py index ce78de4..66a6251 100644 --- a/settings.py +++ b/settings.py @@ -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"Failed to modify Setting: {e.orig}", "danger" ) diff --git a/templates/dups.html b/templates/dups.html index 4e70837..da461f2 100644 --- a/templates/dups.html +++ b/templates/dups.html @@ -31,7 +31,6 @@ function ResetPageSize() { - console.log( $("#pagesize").val() ) $("#psform").submit() return false; } diff --git a/templates/faces.html b/templates/faces.html index 564d324..dbc7305 100644 --- a/templates/faces.html +++ b/templates/faces.html @@ -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}} ) }); diff --git a/templates/refimg.html b/templates/refimg.html index 81d1971..0e17ac5 100644 --- a/templates/refimg.html +++ b/templates/refimg.html @@ -31,6 +31,7 @@ {% block script_content %}