diff --git a/TODO b/TODO index d5bb0bd..ac30fb9 100644 --- a/TODO +++ b/TODO @@ -1,32 +1,32 @@ ### GENERAL * get all status messages to use toasts AND get func to also increase/descrease the job counter as appropriate) - [DONE] all (success/creation) status messages use toasts - -- any non-sucess still stays a top of the page as an alert (for now?) -- [DONE] make a helper func for setting toast body and use it in base.html && file_support.js -- [DONE] make a helper func for setting 'Active Jobs' text/badge and call it when document ready (rather/both than start of base.html) -- [DONE] trigger a timeout to play back pa_job_mgr message to FE and reset 'Active Jobs' text/badge until it hits 0 - -- [DONE] (re)start this code if any new jobs is created (on move only for now - in the long run all job creation should consider this POST/json model) + -- [DONE] (re)start this code if any new jobs is created (on move ONLY FOR NOW + -- [DONE] make js StatusMsg() take a 'data' (json response) and process that + -- [DONE] make it include message from the API endpoint doing the work, not in the js code... -- [TODO] fix base.html to only call toast() and only in document.ready() - -- [TODO] this means handling danger, and persistent / no time-out toast()s + -- [DONE] this means handling danger, and persistent / no time-out toast()s -- [DONE] warning works now (colors, etc.) - -- [TODO] have not thought about danger at all (the StatusMsg() code should work) - but missing Clear*() and persistence - * [TODO] delete files should behave like /move_files (stay on same page, job start with toast(), etc.) - * [TODO] ALL job creation should follow above pattern + -- [DONE] clean up has to be a POST back to server to clear DB (jscript/async has no other way) + -- [TODO] go through the crazy persistent status msgs for checkdups, etc. and make sure they all work + + * 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) + -- ONLY time this will fail is multiple status messages (which can occur I believe if a Wake of job mgr and then a job is created in DB, the success will only be shown) + -- [TODO] simple fix will be to get 'hidden' jobs (wake job_mgr and maybe? metadata) to post failure events to the JobMgr_FE DB queue + -- [TODO] when ALL converted, replace 'alert="..."' with 'status="..."' + + * delete files should behave like /move_files (stay on same page) as well as the status messages above * change the rotation code to use that jpeg util to reduce/remove compression loss? * ignore face should ignore ALL matching faces (re: Declan) - * should be using jsonify to return real json to my API calls, e.g: - response = make_response( - jsonify( - {"message": str(FLAMSG_ERR_SEC_ACCESS_DENIED), "severity": "danger"} - ), - 401, - ) - response.headers["Content-Type"] = "application/json" - return response - * should allow context menu from View thumbs (particularly useful on search) to show other files around this one by date (maybe that folder or something?) * could get better AI optim, by keeping track of just new files since scan (even if we did this from the DB), @@ -39,6 +39,8 @@ --> OR? https://jsmpeg.com/ --> OR? convert all videos to mp4/webm + * consider whether FE_MSG should exist without a job #, and/or a sep. table, etc. + * delete folder * allow joblog search (less needed with logs visible on a given file now) diff --git a/files.py b/files.py index 27b6c51..3084a68 100644 --- a/files.py +++ b/files.py @@ -590,7 +590,10 @@ def move_files(): for el in request.form: jex.append( JobExtra( name=f"{el}", value=request.form[el] ) ) job=NewJob( "move_files", 0, None, jex ) - return make_response( jsonify( job_id=job.id, status="success" ) ) + return make_response( jsonify( + job_id=job.id, + message=f"Created Job #{job.id} to move selected file(s)", + status="success", alert="success" ) ) @login_required @app.route("/viewlist", methods=["POST"]) diff --git a/internal/js/files_support.js b/internal/js/files_support.js index 5bca28f..29d2f74 100644 --- a/internal/js/files_support.js +++ b/internal/js/files_support.js @@ -64,7 +64,7 @@ function MoveSubmit() // reorder the images via ecnt again, so 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){ st=Object; st.message="Created Job #" + data.job_id + " to move selected file(s)"; st.alert="success"; StatusMsg(st); CheckForJobs(); return false; } }) + $.ajax({ type: 'POST', data: $('#mv_fm').serialize(), url: '/move_files', success: function(data){ console.log(data); StatusMsg(data); CheckForJobs(); return false; } }) } // show the DBox for a move file, includes all thumbnails of selected files to move diff --git a/internal/js/jobs.js b/internal/js/jobs.js index 61f3fec..25a64f4 100644 --- a/internal/js/jobs.js +++ b/internal/js/jobs.js @@ -1,66 +1,56 @@ +// global +var next_toast_id=1 + +function NewToast(data) +{ + // make new div, include data.alert as background colour, and data.message as toast body + d_id='st' + String(next_toast_id) + div='
+ ` + // insert this as the first element in the status_container + $('#status_container').prepend(div) + + // make sure we have a new id for next toast + next_toast_id++ + + return d_id +} + // create a bs toast in the status_container // can reuse any that are hidden, OR, create a new one by appending as needed (so we can have 2+ toasts on screen) function StatusMsg(st) { - console.log( 'StatusMsg() -> ' + st.alert + ': ' + st.message ) - // look for any '.hide' and '.toast' - if( $('.toast.hide').length !== 0 ) + el=NewToast(st) + $('#' + el ).toast("show") + // if there is a job_id, then clear the message for it or it will be picked up again on reload + // BUT, we dont want to do this immediately, should hook on close, but for + // now, we will do this to get a first pass working + if( st.job_id !== undefined ) { - // as there may be more than 1 and as bs toast deals with ordering on screen, so just grab first() - tid=$('.toast.hide').first().attr('id') - // reset body, and the text-* and bg-* class for success, danger, etc. - $('#'+tid ).find( '.toast-body').html(st.message) - $('#'+tid ).removeClass( function( index, className ) { return (className.match( /(^|\s)(bg-|text-)\S+/g) || []).join(' ') } ) - $('#'+tid ).addClass( 'bg-' + st.alert ) - // get rid of white on button (if its there) - $('#'+tid ).find( 'button' ).removeClass('btn-close-white') - if( st.alert == "success" || st.alert == "danger" ) - { - $('#'+tid ).addClass( 'text-white' ) - $('#'+tid ).find( 'button' ).addClass('btn-close-white') - } - // show the popup (by default it fades) - $('#'+tid ).toast("show") + $.ajax( { type: 'POST', url: '/clearmsgforjob/'+st.job_id, success: function(data) { } } ) } - else - { - // find the id of the 'last' toast (either there are none, or they are all visible [note: we are in the else already]) - tmp=$('.toast').last().attr('id') - // if none, there are no toasts at all, so make '#1' - if( tmp== '' ) - tid=1 - else - { - // skip 'st' at front of DOM id, and then increment to get id for new one - tid=tmp.substr(2) - tid++ - } - // make new div, include st.alert as background colour, and st.message as toast body - div=' - ` - // can be appended straight after st1 as the .toast("show") deals with display ordering - $('#st1').append(div) - // show the popup (by default it fades) - $('#st' + tid ).toast("show") - } } // this will make the active jobs badge red with a > 0 value, or navbar colours @@ -95,7 +85,7 @@ function CheckForJobs() SetActiveJobsBadge(data.num_active_jobs) if( data.num_active_jobs > 0 ) { - setTimeout( function() { CheckForJobCompletion() }, 1000 ); + setTimeout( function() { CheckForJobs() }, 1000 ); } }, } ) diff --git a/job.py b/job.py index a59e9ae..72f9e35 100644 --- a/job.py +++ b/job.py @@ -90,7 +90,6 @@ def GetJM_Message(): # ClearJM_Message: used in html to clear any message just displayed ################################################################################ def ClearJM_Message(id): - print("ClearJM_Message called") PA_JobManager_Message.query.filter(PA_JobManager_Message.id==id).delete() db.session.commit() return @@ -313,9 +312,21 @@ def CheckForJobs(): for msg in PA_JobManager_Message.query.all(): print("there is a PA_J_MGR status message" ) u='Job # ' + str(msg.job_id) + ': ' - sts.append( { 'message': u+msg.message, 'alert': msg.alert } ) + sts.append( { 'message': u+msg.message, 'alert': msg.alert, 'job_id': msg.job_id } ) 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/