diff --git a/TODO b/TODO index ac30fb9..d78f430 100644 --- a/TODO +++ b/TODO @@ -1,17 +1,7 @@ ### 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 - -- [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 - -- [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() - -- [DONE] this means handling danger, and persistent / no time-out toast()s - -- [DONE] warning works now (colors, etc.) - -- [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 + -- [TODO] ensure all pa_job_mgr jobs are sending messages back to the FE -- SHOULD??? I just hook FinishJob??? * should be using jsonify to return real json to my API calls, e.g: use make_response( jsonify (... ) ) @@ -19,7 +9,8 @@ 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="..."' + -- [TODO] -- change class Status to class UILog + -- [TODO] -- change alert to level * delete files should behave like /move_files (stay on same page) as well as the status messages above diff --git a/files.py b/files.py index 3084a68..dbbf540 100644 --- a/files.py +++ b/files.py @@ -593,7 +593,7 @@ def move_files(): return make_response( jsonify( job_id=job.id, message=f"Created Job #{job.id} to move selected file(s)", - status="success", alert="success" ) ) + level="success", alert="success", persistent=False, cant_close=False ) ) @login_required @app.route("/viewlist", methods=["POST"]) diff --git a/internal/js/jobs.js b/internal/js/jobs.js index 25a64f4..f26bab2 100644 --- a/internal/js/jobs.js +++ b/internal/js/jobs.js @@ -3,11 +3,14 @@ var next_toast_id=1 function NewToast(data) { + console.log(data) // make new div, include data.alert as background colour, and data.message as toast body d_id='st' + String(next_toast_id) div='
Job # ' + str(msg.job_id) + ': ' - sts.append( { 'message': u+msg.message, 'alert': msg.alert, 'job_id': msg.job_id } ) + sts.append( { 'message': u+msg.message, 'alert': msg.alert, 'job_id': msg.job_id, 'persistent': msg.persistent, 'cant_close': msg.cant_close } ) return make_response( jsonify( num_active_jobs=num, sts=sts ) ) ############################################################################### diff --git a/pa_job_manager.py b/pa_job_manager.py index 49dc19d..deb52aa 100644 --- a/pa_job_manager.py +++ b/pa_job_manager.py @@ -503,6 +503,8 @@ class PA_JobManager_FE_Message(Base): job_id = Column(Integer, ForeignKey('job.id') ) alert = Column(String) message = Column(String) + persistent = Column(Boolean) + cant_close = Column(Boolean) def __repr__(self): return "here to restart or cancel' ) + MessageToFE( job.id, "danger", f'Stale job, click  here to restart or cancel', True, False ) session.commit() continue if job.pa_job_state == 'New': @@ -930,7 +932,7 @@ def HandleJobs(first_run=False): # threading.Thread(target=RunJob, args=(job,)).start() except Exception as e: try: - MessageToFE( job.id, "danger", "Failed with: {} (try job log for details)".format(e) ) + MessageToFE( job.id, "danger", "Failed with: {} (try job log for details)".format(e), True, False ) except Exception as e2: print("ERROR: Failed to let front-end know, but back-end Failed to run job (id: {}, name: {} -- orig exep was: {}, this exception was: {})".format( job.id, job.name, e, e2) ) print("INFO: PA job manager is waiting for a job") @@ -954,7 +956,7 @@ def JobScanNow(job): JobProgressState( job, "In Progress" ) ProcessImportDirs(job) FinishJob( job, "Completed (scan for new files)" ) - MessageToFE( job.id, "success", "Completed (scan for new files)" ) + MessageToFE( job.id, "success", "Completed (scan for new files)", False, False ) return ############################################################################## @@ -964,7 +966,7 @@ def JobScanStorageDir(job): JobProgressState( job, "In Progress" ) ProcessStorageDirs(job) FinishJob( job, "Completed (scan for new files)" ) - MessageToFE( job.id, "success", "Completed (scan for new files)" ) + MessageToFE( job.id, "success", "Completed (scan for new files)", False, False ) return @@ -1078,7 +1080,7 @@ def JobForceScan(job): ProcessImportDirs(job) ProcessStorageDirs(job) FinishJob(job, "Completed (forced remove and recreation of all file data)") - MessageToFE( job.id, "success", "Completed (forced remove and recreation of all file data)" ) + MessageToFE( job.id, "success", "Completed (forced remove and recreation of all file data)", False, False ) return ############################################################################## @@ -1319,6 +1321,10 @@ def MoveFileToRecycleBin(job,del_me): bin_path=session.query(Path).join(PathType).filter(PathType.name=='Bin').first() parent_dir=session.query(Dir).join(PathDirLink).filter(PathDirLink.path_id==bin_path.id).first() + # check/delete if we already have a deleted file of this name/number (only # happened in testing, but jic) + # 99.9% of the time, this will just delete nothing + session.query(DelFile).filter(DelFile.file_eid==del_me.id).delete() + # if we ever need to restore, lets remember this file's original path # (use a string in case the dir/path is ever deleted from FS (and then DB) and we need to recreate) del_file_details = DelFile( file_eid=del_me.id, orig_path_prefix=del_me.in_dir.in_path.path_prefix ) @@ -2036,7 +2042,7 @@ def JobCheckForDups(job): for row in res: if row.count > 0: AddLogForJob(job, f"Found duplicates, Creating Status message in front-end for attention") - MessageToFE( job.id, "danger", f'Found duplicate(s), click  here to finalise import by removing duplicates' ) + MessageToFE( job.id, "danger", f'Found duplicate(s), click  here to finalise import by removing duplicates', True, True ) else: FinishJob(job, f"No duplicates found") FinishJob(job, f"Finished looking for duplicates") @@ -2107,7 +2113,8 @@ def JobRemoveDups(job): # Need to put another checkdups job in now to force / validate we have no dups next_job=NewJob( "checkdups" ) - AddLogForJob(job, "adding job id={} {} to confirm there are no more duplicates".format( next_job.id, next_job.id, next_job.name ) ) + AddLogForJob(job, f"adding job id={next_job.id} {next_job.name} to confirm there are no more duplicates" ) + MessageToFE( job.id, "success", f"Finished Job#{job.id} removing duplicate files", False, False ) return #################################################################################################################################### @@ -2137,7 +2144,7 @@ def JobMoveFiles(job): move_me=session.query(Entry).get(jex.value) MoveEntriesToOtherFolder( job, move_me, dst_storage_path, f"{prefix}{suffix}" ) next_job=NewJob( "checkdups" ) - MessageToFE( job.id, "success", "Completed (move of selected files)" ) + MessageToFE( job.id, "success", "Completed (move of selected files)", False, False ) FinishJob(job, f"Finished move selected file(s)") return @@ -2152,7 +2159,7 @@ def JobDeleteFiles(job): del_me=session.query(Entry).join(File).filter(Entry.id==jex.value).first() MoveFileToRecycleBin(job,del_me) next_job=NewJob( "checkdups" ) - MessageToFE( job.id, "success", "Completed (delete of selected files)" ) + MessageToFE( job.id, "success", "Completed (delete of selected files)", False, False ) FinishJob(job, f"Finished deleting selected file(s)") return @@ -2167,7 +2174,7 @@ def JobRestoreFiles(job): restore_me=session.query(Entry).join(File).filter(Entry.id==jex.value).first() RestoreFile(job,restore_me) next_job=NewJob( "checkdups" ) - MessageToFE( job.id, "success", "Completed (restore of selected files)" ) + MessageToFE( job.id, "success", "Completed (restore of selected files)", False, False ) FinishJob(job, f"Finished restoring selected file(s)") return diff --git a/status.py b/status.py index 311ee76..0b25ce1 100644 --- a/status.py +++ b/status.py @@ -5,18 +5,18 @@ from shared import PA # including when duplicates are found on import. These status messages are exposed into # the html files, and they show once for success/green, and sticky for danger/red class Status(PA): - alert="success" + level="success" message="" def GetAlert(self): - return self.alert + return self.level def GetMessage(self): return self.message - def SetMessage(self, msg, al="success"): + def SetMessage(self, msg, l="success"): self.message=msg - self.alert=al + self.level=l return def AppendMessage(self, msg): @@ -24,7 +24,7 @@ class Status(PA): return def ClearStatus(self): - self.alert="success" + self.level="success" self.message="" return "" diff --git a/tables.sql b/tables.sql index d5e414d..009df67 100644 --- a/tables.sql +++ b/tables.sql @@ -160,7 +160,7 @@ create table JOBEXTRA ( ID integer, JOB_ID integer, NAME varchar(32), VALUE varc create table JOBLOG ( ID integer, JOB_ID integer, LOG_DATE timestamptz, LOG varchar, constraint PK_JL_ID primary key(ID), constraint FK_JL_JOB_ID foreign key(JOB_ID) references JOB(ID) ); -create table PA_JOB_MANAGER_FE_MESSAGE ( ID integer, JOB_ID integer, ALERT varchar(16), MESSAGE varchar(1024), +create table PA_JOB_MANAGER_FE_MESSAGE ( ID integer, JOB_ID integer, ALERT varchar(16), MESSAGE varchar(1024), PERSISTENT boolean, CANT_CLOSE boolean, constraint PA_JOB_MANAGER_FE_ACKS_ID primary key(ID), constraint FK_PA_JOB_MANAGER_FE_MESSAGE_JOB_ID foreign key(JOB_ID) references JOB(ID) ); diff --git a/templates/base.html b/templates/base.html index 0803ade..058bae1 100644 --- a/templates/base.html +++ b/templates/base.html @@ -128,40 +128,14 @@
- - {% if GetJM_Message() != None %} - {% set msg=GetJM_Message() %} - - {% if request.endpoint != "fix_dups" and request.endpoint != "rm_dups" and request.endpoint != "stale_jobs" %} - {% if msg.alert != "success" %} -
- {% if msg.job.name != "checkdups" %} -
- - {% endif %} - {% if msg.job_id %} - Job #{{msg.job_id}}: - {% endif %} - {{msg.message|safe}} -
-
- {# if a JM is a danger message, allow code to remove the status, it should be 'permanent' until addressed -- e.g. you have duplicates, fix them #} - {% if msg.alert != "danger" %} - {% set dont_print=ClearJM_Message(msg.id) %} - {% endif %} - {% endif %} - {% endif %} - {% endif %} -{% endif %} +{% endif %} {# not InDBox #} {% block main_content %} {% endblock main_content %} {% if not InDBox %} {%block script_content %}{% endblock script_content %} -
+