renamed toast.js to jobs.js and moved Job related calls to jobs.py form files.py AND get job.py to allow job_mgr msgs to go to F/E via a POST of /checkforjobs (picked up in templates/base.html). move files also calls new CheckForJobs() to pick up when move job finishes without needing a page reload
This commit is contained in:
21
TODO
21
TODO
@@ -1,4 +1,18 @@
|
|||||||
### GENERAL
|
### 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)
|
||||||
|
-- [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] 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
|
||||||
|
|
||||||
* change the rotation code to use that jpeg util to reduce/remove compression loss?
|
* change the rotation code to use that jpeg util to reduce/remove compression loss?
|
||||||
|
|
||||||
* ignore face should ignore ALL matching faces (re: Declan)
|
* ignore face should ignore ALL matching faces (re: Declan)
|
||||||
@@ -13,13 +27,6 @@
|
|||||||
response.headers["Content-Type"] = "application/json"
|
response.headers["Content-Type"] = "application/json"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
* 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 (always?)
|
|
||||||
-- [DONE] make a helper func for setting toast body and use it in base.html && file_support.js
|
|
||||||
-- [TODO] make a helper func for setting 'Active Jobs' text/badge and call it when document ready (rather/both than start of base.html)
|
|
||||||
-- should allow all JM Messages, or other messages to be an active Ajax poll until a job has completed
|
|
||||||
|
|
||||||
* 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?)
|
* 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),
|
* could get better AI optim, by keeping track of just new files since scan (even if we did this from the DB),
|
||||||
|
|||||||
32
files.py
32
files.py
@@ -141,38 +141,6 @@ class FileType(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<id: {self.id}, name={self.name}>"
|
return f"<id: {self.id}, name={self.name}>"
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Class describing PA_JobManager_Message and in the DB (via sqlalchemy)
|
|
||||||
# the job manager can send a message back to the front end (this code) via the
|
|
||||||
# DB. has to be about a specific job_id and is success/danger, etc. (alert)
|
|
||||||
# and a message
|
|
||||||
################################################################################
|
|
||||||
class PA_JobManager_Message(db.Model):
|
|
||||||
__tablename__ = "pa_job_manager_fe_message"
|
|
||||||
id = db.Column(db.Integer, db.Sequence('pa_job_manager_fe_message_id_seq'), primary_key=True )
|
|
||||||
job_id = db.Column(db.Integer, db.ForeignKey('job.id') )
|
|
||||||
alert = db.Column(db.String)
|
|
||||||
message = db.Column(db.String)
|
|
||||||
job = db.relationship ("Job" )
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<id: {self.id}, job_id: {self.job_id}, alert: {self.alert}, message: {self.message}, job: {self.job}"
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# GetJM_Message: used in html to display any message for this front-end
|
|
||||||
################################################################################
|
|
||||||
def GetJM_Message():
|
|
||||||
msg=PA_JobManager_Message.query.first()
|
|
||||||
return msg
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# ClearJM_Message: used in html to clear any message just displayed
|
|
||||||
################################################################################
|
|
||||||
def ClearJM_Message(id):
|
|
||||||
PA_JobManager_Message.query.filter(PA_JobManager_Message.id==id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# util function to just update the current/first/last positions needed for
|
# util function to just update the current/first/last positions needed for
|
||||||
# viewing / using pa_user_state DB table
|
# viewing / using pa_user_state DB table
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function MoveSubmit()
|
|||||||
// reorder the images via ecnt again, so highlighting can work
|
// 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++ } )
|
document.mf_id=0; $('.figure').each( function() { $(this).attr('ecnt', document.mf_id ); document.mf_id++ } )
|
||||||
$('#dbox').modal('hide')
|
$('#dbox').modal('hide')
|
||||||
$.ajax({ type: 'POST', data: $('#mv_fm').serialize(), url: '/move_files', success: function(data){ st=Object; st.message="Created <a class='link-light' href=/job/" + data.job_id + ">Job #" + data.job_id + "</a> to move selected file(s)"; st.alert="success"; StatusMsg(st); return false; } })
|
$.ajax({ type: 'POST', data: $('#mv_fm').serialize(), url: '/move_files', success: function(data){ st=Object; st.message="Created <a class='link-light' href=/job/" + data.job_id + ">Job #" + data.job_id + "</a> to move selected file(s)"; st.alert="success"; StatusMsg(st); CheckForJobs(); return false; } })
|
||||||
}
|
}
|
||||||
|
|
||||||
// show the DBox for a move file, includes all thumbnails of selected files to move
|
// show the DBox for a move file, includes all thumbnails of selected files to move
|
||||||
|
|||||||
103
internal/js/jobs.js
Normal file
103
internal/js/jobs.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
// 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")
|
||||||
|
}
|
||||||
|
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='<div id="st' + tid + '" class="toast hide align-items-center border-0'
|
||||||
|
if( st.alert == "success" || st.alert == "danger" )
|
||||||
|
div += ' text-white'
|
||||||
|
div += ' bg-' + st.alert
|
||||||
|
div += `" role="alert" aria-live="assertive" aria-atomic="true">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="toast-body">
|
||||||
|
`
|
||||||
|
div += st.message
|
||||||
|
div += `
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close me-2 m-auto
|
||||||
|
`
|
||||||
|
if( st.alert == "success" || st.alert == "danger" )
|
||||||
|
div =+ ' btn-close-white'
|
||||||
|
div += `
|
||||||
|
" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</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
|
||||||
|
// if 0 (effectively hiding it, but leaving the same width)
|
||||||
|
function SetActiveJobsBadge(num_jobs)
|
||||||
|
{
|
||||||
|
if( num_jobs > 0 )
|
||||||
|
$('#num_active_jobs').removeClass("invisible")
|
||||||
|
else
|
||||||
|
$('#num_active_jobs').addClass("invisible")
|
||||||
|
$('#num_active_jobs').html(num_jobs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function is called either when we load and PA page and active jobs > 0
|
||||||
|
// OR, when a new job is created in the F/E and therefore active jobs > 0
|
||||||
|
// it keeps looking to see if the pa_job_manager has sent a response (via the DB)
|
||||||
|
// if so, it handles the response(s) with toast()s and updates the active job
|
||||||
|
// badge in the navbar. If all jobs are complete it stops calling itself
|
||||||
|
// after a 1 second timeout
|
||||||
|
function CheckForJobs()
|
||||||
|
{
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
type: 'POST', url: '/checkforjobs',
|
||||||
|
success: function(data) {
|
||||||
|
data.sts.forEach(
|
||||||
|
function(el)
|
||||||
|
{
|
||||||
|
StatusMsg(el)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SetActiveJobsBadge(data.num_active_jobs)
|
||||||
|
if( data.num_active_jobs > 0 )
|
||||||
|
{
|
||||||
|
setTimeout( function() { CheckForJobCompletion() }, 1000 );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
// create a bs toast in the status_container
|
|
||||||
function StatusMsg(st)
|
|
||||||
{
|
|
||||||
// look for first '.hide' in #status_container (there may be more than 1)
|
|
||||||
if( $('.toast.hide').length !== 0 )
|
|
||||||
{
|
|
||||||
tid=$('.toast.hide').first().attr('id')
|
|
||||||
$('#'+tid ).find( '.toast-body').html(st.message)
|
|
||||||
$('#'+tid ).removeClass( function( index, className ) { return (className.match( /(^|\s)bg-\S+/g) || []).join(' ') } )
|
|
||||||
$('#'+tid ).addClass( 'bg-' + st.alert )
|
|
||||||
$('#'+tid ).toast("show")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp=$('.toast').last().attr('id')
|
|
||||||
if( tmp== '' )
|
|
||||||
tid=1
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// skip 'st'
|
|
||||||
tid=tmp.substr(2)
|
|
||||||
tid++
|
|
||||||
}
|
|
||||||
div='<div id="st' + tid + '" class="toast hide align-items-center text-white border-0 bg-' + st.alert
|
|
||||||
div += `" role="alert" aria-live="assertive" aria-atomic="true">
|
|
||||||
<div class="d-flex">
|
|
||||||
<div class="toast-body">
|
|
||||||
`
|
|
||||||
div += st.message
|
|
||||||
div += `
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
// can be appended straight after st1 as the .toast("show") deals with display ordering
|
|
||||||
$('#st1').append(div)
|
|
||||||
$('#st' + tid ).toast("show")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
job.py
52
job.py
@@ -1,16 +1,15 @@
|
|||||||
from wtforms import SubmitField, StringField, FloatField, HiddenField, validators, Form
|
from wtforms import SubmitField, StringField, FloatField, HiddenField, validators, Form
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from flask import request, render_template, redirect
|
from flask import request, render_template, redirect, make_response, jsonify, url_for
|
||||||
from settings import Settings
|
from settings import Settings
|
||||||
from main import db, app, ma
|
from main import db, app, ma
|
||||||
from sqlalchemy import Sequence, func
|
from sqlalchemy import Sequence, func
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from flask_login import login_required, current_user
|
|
||||||
import pytz
|
import pytz
|
||||||
import socket
|
import socket
|
||||||
from shared import PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT, NEWEST_LOG_LIMIT, OLDEST_LOG_LIMIT
|
from shared import PA, PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT, NEWEST_LOG_LIMIT, OLDEST_LOG_LIMIT
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from sqlalchemy.dialects.postgresql import INTERVAL
|
from sqlalchemy.dialects.postgresql import INTERVAL
|
||||||
from sqlalchemy.sql.functions import concat
|
from sqlalchemy.sql.functions import concat
|
||||||
@@ -63,6 +62,38 @@ class Job(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<id: {}, start_time: {}, last_update: {}, name: {}, state: {}, num_files: {}, current_file_num: {}, current_file: {}, pa_job_state: {}, wait_for: {}, extra: {}, logs: {}>".format(self.id, self.start_time, self.last_update, self.name, self.state, self.num_files, self.current_file_num, self.current_file, self.pa_job_state, self.wait_for, self.extra, self.logs)
|
return "<id: {}, start_time: {}, last_update: {}, name: {}, state: {}, num_files: {}, current_file_num: {}, current_file: {}, pa_job_state: {}, wait_for: {}, extra: {}, logs: {}>".format(self.id, self.start_time, self.last_update, self.name, self.state, self.num_files, self.current_file_num, self.current_file, self.pa_job_state, self.wait_for, self.extra, self.logs)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Class describing PA_JobManager_Message and in the DB (via sqlalchemy)
|
||||||
|
# the job manager can send a message back to the front end (this code) via the
|
||||||
|
# DB. has to be about a specific job_id and is success/danger, etc. (alert)
|
||||||
|
# and a message
|
||||||
|
################################################################################
|
||||||
|
class PA_JobManager_Message(db.Model):
|
||||||
|
__tablename__ = "pa_job_manager_fe_message"
|
||||||
|
id = db.Column(db.Integer, db.Sequence('pa_job_manager_fe_message_id_seq'), primary_key=True )
|
||||||
|
job_id = db.Column(db.Integer, db.ForeignKey('job.id') )
|
||||||
|
alert = db.Column(db.String)
|
||||||
|
message = db.Column(db.String)
|
||||||
|
job = db.relationship ("Job" )
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<id: {self.id}, job_id: {self.job_id}, alert: {self.alert}, message: {self.message}, job: {self.job}"
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# GetJM_Message: used in html to display any message for this front-end
|
||||||
|
################################################################################
|
||||||
|
def GetJM_Message():
|
||||||
|
msg=PA_JobManager_Message.query.first()
|
||||||
|
return msg
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# 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
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Used in main html to show a red badge of # jobs to draw attention there are
|
# Used in main html to show a red badge of # jobs to draw attention there are
|
||||||
@@ -269,6 +300,21 @@ def joblog_search():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# / -> 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("/checkforjobs", methods=["POST"])
|
||||||
|
@login_required
|
||||||
|
def CheckForJobs():
|
||||||
|
num=GetNumActiveJobs()
|
||||||
|
sts=[]
|
||||||
|
print("CheckForJobs called" )
|
||||||
|
for msg in PA_JobManager_Message.query.all():
|
||||||
|
print("there is a PA_J_MGR status message" )
|
||||||
|
u='<a class="link-light" href="' + url_for('joblog', id=msg.job_id) + '">Job # ' + str(msg.job_id) + '</a>: '
|
||||||
|
sts.append( { 'message': u+msg.message, 'alert': msg.alert } )
|
||||||
|
return make_response( jsonify( num_active_jobs=num, sts=sts ) )
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# This func creates a new filter in jinja2 to format the time from the db in a
|
# This func creates a new filter in jinja2 to format the time from the db in a
|
||||||
|
|||||||
4
main.py
4
main.py
@@ -57,9 +57,9 @@ Compress(app)
|
|||||||
|
|
||||||
################################# Now, import separated class files ###################################
|
################################# Now, import separated class files ###################################
|
||||||
from ai import aistats
|
from ai import aistats
|
||||||
from files import Entry, GetJM_Message, ClearJM_Message
|
from files import Entry
|
||||||
from person import Person
|
from person import Person
|
||||||
from job import Job, GetNumActiveJobs
|
from job import Job, GetNumActiveJobs, GetJM_Message, ClearJM_Message
|
||||||
from settings import Settings
|
from settings import Settings
|
||||||
from user import PAUser
|
from user import PAUser
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<script src="{{ url_for( 'internal', filename='upstream/bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js')}}"></script>
|
<script src="{{ url_for( 'internal', filename='upstream/bootstrap-5.0.2-dist/js/bootstrap.bundle.min.js')}}"></script>
|
||||||
<script src="{{ url_for( 'internal', filename='upstream/jquery.contextMenu.min.js')}}"></script>
|
<script src="{{ url_for( 'internal', filename='upstream/jquery.contextMenu.min.js')}}"></script>
|
||||||
<script src="{{ url_for( 'internal', filename='upstream/jquery.ui.position.min.js')}}"></script>
|
<script src="{{ url_for( 'internal', filename='upstream/jquery.ui.position.min.js')}}"></script>
|
||||||
<script src="{{ url_for( 'internal', filename='js/toast.js')}}"></script>
|
<script src="{{ url_for( 'internal', filename='js/jobs.js')}}"></script>
|
||||||
|
|
||||||
<link rel="shortcut icon" href="{{ url_for('internal', filename='favicon.ico') }}">
|
<link rel="shortcut icon" href="{{ url_for('internal', filename='favicon.ico') }}">
|
||||||
|
|
||||||
@@ -106,12 +106,7 @@
|
|||||||
</div class="nav-item dropdown">
|
</div class="nav-item dropdown">
|
||||||
<div class="d-flex nav-link flex-grow-1 justify-content-center p-0">
|
<div class="d-flex nav-link flex-grow-1 justify-content-center p-0">
|
||||||
<a href="{{url_for('jobs')}}"}}<span class="navbar-text">Active Jobs:
|
<a href="{{url_for('jobs')}}"}}<span class="navbar-text">Active Jobs:
|
||||||
{% set num_active_jobs = GetNumActiveJobs() %}
|
<span id="num_active_jobs" class="badge badge-pill bg-danger invisible">0</></span>
|
||||||
{% if num_active_jobs > 0 %}
|
|
||||||
<span id="num_active_jobs" class="badge bg-danger text-white"}}>{{num_active_jobs}}</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="badge">0</span>
|
|
||||||
{% endif %}
|
|
||||||
</a>
|
</a>
|
||||||
</div class="nav-item">
|
</div class="nav-item">
|
||||||
|
|
||||||
@@ -136,10 +131,11 @@
|
|||||||
|
|
||||||
{% if GetJM_Message() != None %}
|
{% if GetJM_Message() != None %}
|
||||||
{% set msg=GetJM_Message() %}
|
{% set msg=GetJM_Message() %}
|
||||||
|
<!-- if we are fixing things dont put up alert -->
|
||||||
{% if request.endpoint != "fix_dups" and request.endpoint != "rm_dups" and request.endpoint != "stale_jobs" %}
|
{% if request.endpoint != "fix_dups" and request.endpoint != "rm_dups" and request.endpoint != "stale_jobs" %}
|
||||||
{% if msg.alert != "success" %}
|
{% if msg.alert != "success" %}
|
||||||
<div class="py-2 mx-1 alert alert-{{msg.alert}}">
|
<div class="py-2 mx-1 alert alert-{{msg.alert}}">
|
||||||
{% if msg.alert != "success" and msg.job.name != "checkdups" %}
|
{% if msg.job.name != "checkdups" %}
|
||||||
<form id="_dismiss" action="{{url_for('clear_jm_msg', id=msg.id)}}" method="POST">
|
<form id="_dismiss" action="{{url_for('clear_jm_msg', id=msg.id)}}" method="POST">
|
||||||
<button type="button" class="close btn border-secondary me-3" aria-label="Close" onClick="$('#_dismiss').submit()">
|
<button type="button" class="close btn border-secondary me-3" aria-label="Close" onClick="$('#_dismiss').submit()">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
@@ -176,12 +172,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
<!-- f/e messages are resident in memory of the page being rendered, just process now -->
|
||||||
{% if GetMessage()|length %}
|
{% if GetMessage()|length %}
|
||||||
msg = "{{ GetMessage()|safe }}"
|
msg = "{{ GetMessage()|safe }}"
|
||||||
msg=msg.replace('href=', 'class=link-light href=')
|
msg=msg.replace('href=', 'class=link-light href=')
|
||||||
st=Object; st.message=msg; st.alert="success"; StatusMsg(st)
|
st=Object; st.message=msg; st.alert='{{GetAlert()}}'; StatusMsg(st)
|
||||||
{{ ClearStatus() }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
CheckForJobs()
|
||||||
|
/*
|
||||||
|
<!-- this this is totally useless as can only live for this 1 page render anyway -->
|
||||||
|
{{ ClearStatus() }}
|
||||||
{% if GetJM_Message() != None and GetJM_Message().alert == "success" %}
|
{% if GetJM_Message() != None and GetJM_Message().alert == "success" %}
|
||||||
msg="{{GetJM_Message().message}}"
|
msg="{{GetJM_Message().message}}"
|
||||||
msg=msg.replace('href=', 'class=link-light href=')
|
msg=msg.replace('href=', 'class=link-light href=')
|
||||||
@@ -189,6 +189,7 @@
|
|||||||
StatusMsg(st)
|
StatusMsg(st)
|
||||||
{% set dont_print=ClearJM_Message(GetJM_Message().id) %}
|
{% set dont_print=ClearJM_Message(GetJM_Message().id) %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
*/
|
||||||
} )
|
} )
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user