diff --git a/app/contributions/tesseract_ocr_pipeline_models/json_routes.py b/app/contributions/tesseract_ocr_pipeline_models/json_routes.py index f90a971f..705fbdb4 100644 --- a/app/contributions/tesseract_ocr_pipeline_models/json_routes.py +++ b/app/contributions/tesseract_ocr_pipeline_models/json_routes.py @@ -25,11 +25,11 @@ def delete_tesseract_model(tesseract_ocr_pipeline_model_id): args=(current_app._get_current_object(), topm.id) ) thread.start() - resonse_data = { + response_data = { 'message': \ f'Tesseract OCR Pipeline Model "{topm.title}" marked for deletion' } - response = jsonify(resonse_data) + response = jsonify(response_data) response.status_code = 202 return response @@ -39,6 +39,8 @@ def delete_tesseract_model(tesseract_ocr_pipeline_model_id): @permission_required('CONTRIBUTE') @content_negotiation(consumes='application/json', produces='application/json') def update_tesseract_ocr_pipeline_model_is_public(tesseract_ocr_pipeline_model_id): + # body: jsonify({'is_public': True}) + # body: jsonify(False) is_public = request.json if not isinstance(is_public, bool): abort(400) diff --git a/app/jobs/__init__.py b/app/jobs/__init__.py index 72244069..11b2ad36 100644 --- a/app/jobs/__init__.py +++ b/app/jobs/__init__.py @@ -2,4 +2,4 @@ from flask import Blueprint bp = Blueprint('jobs', __name__) -from . import routes +from . import routes, json_routes diff --git a/app/jobs/json_routes.py b/app/jobs/json_routes.py new file mode 100644 index 00000000..261fe3cc --- /dev/null +++ b/app/jobs/json_routes.py @@ -0,0 +1,69 @@ +from flask import (abort, current_app, jsonify) +from flask_login import current_user, login_required +from threading import Thread +import os +from app import db +from app.decorators import admin_required, content_negotiation +from app.models import Job, JobInput, JobResult, JobStatus +from . import bp + +@bp.route('/', methods=['DELETE']) +@login_required +@content_negotiation(produces='application/json') +def delete_job(job_id): + def _delete_job(app, job_id): + with app.app_context(): + job = Job.query.get(job_id) + job.delete() + db.session.commit() + + job = Job.query.get_or_404(job_id) + if not (job.user == current_user or current_user.is_administrator()): + abort(403) + thread = Thread( + target=_delete_job, + args=(current_app._get_current_object(), job_id) + ) + thread.start() + response_data = { + 'message': \ + f'Job "{job.title}" marked for deletion' + } + response = jsonify(response_data) + response.status_code = 202 + return response + +@bp.route('//log') +@login_required +@admin_required +def job_log(job_id): + job = Job.query.get_or_404(job_id) + if job.status not in [JobStatus.COMPLETED, JobStatus.FAILED]: + response = {'errors': {'message': 'Job status is not completed or failed'}} + return response, 409 + with open(os.path.join(job.path, 'pipeline_data', 'logs', 'pyflow_log.txt')) as log_file: + log = log_file.read() + return log, 200, {'Content-Type': 'text/plain; charset=utf-8'} + + +@bp.route('//restart', methods=['POST']) +@login_required +def restart_job(job_id): + def _restart_job(app, job_id): + with app.app_context(): + job = Job.query.get(job_id) + job.restart() + db.session.commit() + + job = Job.query.get_or_404(job_id) + if not (job.user == current_user or current_user.is_administrator()): + abort(403) + if job.status == JobStatus.FAILED: + response = {'errors': {'message': 'Job status is not "failed"'}} + return response, 409 + thread = Thread( + target=_restart_job, + args=(current_app._get_current_object(), job_id) + ) + thread.start() + return {}, 202 diff --git a/app/jobs/routes.py b/app/jobs/routes.py index 7dae80e1..f7848db9 100644 --- a/app/jobs/routes.py +++ b/app/jobs/routes.py @@ -26,62 +26,6 @@ def job(job_id): ) -@bp.route('/', methods=['DELETE']) -@login_required -def delete_job(job_id): - def _delete_job(app, job_id): - with app.app_context(): - job = Job.query.get(job_id) - job.delete() - db.session.commit() - - job = Job.query.get_or_404(job_id) - if not (job.user == current_user or current_user.is_administrator()): - abort(403) - thread = Thread( - target=_delete_job, - args=(current_app._get_current_object(), job_id) - ) - thread.start() - return {}, 202 - - -@bp.route('//log') -@login_required -@admin_required -def job_log(job_id): - job = Job.query.get_or_404(job_id) - if job.status not in [JobStatus.COMPLETED, JobStatus.FAILED]: - response = {'errors': {'message': 'Job status is not completed or failed'}} - return response, 409 - with open(os.path.join(job.path, 'pipeline_data', 'logs', 'pyflow_log.txt')) as log_file: - log = log_file.read() - return log, 200, {'Content-Type': 'text/plain; charset=utf-8'} - - -@bp.route('//restart', methods=['POST']) -@login_required -def restart_job(job_id): - def _restart_job(app, job_id): - with app.app_context(): - job = Job.query.get(job_id) - job.restart() - db.session.commit() - - job = Job.query.get_or_404(job_id) - if not (job.user == current_user or current_user.is_administrator()): - abort(403) - if job.status == JobStatus.FAILED: - response = {'errors': {'message': 'Job status is not "failed"'}} - return response, 409 - thread = Thread( - target=_restart_job, - args=(current_app._get_current_object(), job_id) - ) - thread.start() - return {}, 202 - - @bp.route('//inputs//download') @login_required def download_job_input(job_id, job_input_id): diff --git a/app/static/js/Requests/Requests.js b/app/static/js/Requests/Requests.js index 41f05a7f..5c1d4ceb 100644 --- a/app/static/js/Requests/Requests.js +++ b/app/static/js/Requests/Requests.js @@ -1,4 +1,4 @@ -Requests = {}; +let Requests = {}; Requests.JSONfetch = (input, init={}) => { return new Promise((resolve, reject) => { diff --git a/app/static/js/Requests/jobs/jobs.js b/app/static/js/Requests/jobs/jobs.js new file mode 100644 index 00000000..f1179658 --- /dev/null +++ b/app/static/js/Requests/jobs/jobs.js @@ -0,0 +1,23 @@ +/***************************************************************************** +* Jobs * +* Fetch requests for /jobs routes * +*****************************************************************************/ +Requests.jobs = {}; + +Requests.jobs.entity = {}; + +Requests.jobs.entity.delete = (jobId) => { + let input = `/jobs/${jobId}`; + let init = { + method: 'DELETE' + }; + return Requests.JSONfetch(input, init); +} + +Requests.jobs.entity.log = (jobId) => { + let input = `/jobs/${jobId}/log`; + let init = { + method: 'GET' + }; + return Requests.JSONfetch(input, init); +} diff --git a/app/static/js/ResourceDisplays/JobDisplay.js b/app/static/js/ResourceDisplays/JobDisplay.js index 8b94e49b..df8eb7b5 100644 --- a/app/static/js/ResourceDisplays/JobDisplay.js +++ b/app/static/js/ResourceDisplays/JobDisplay.js @@ -2,11 +2,6 @@ class JobDisplay extends ResourceDisplay { constructor(displayElement) { super(displayElement); this.jobId = this.displayElement.dataset.jobId; - this.displayElement - .querySelector('.action-button[data-action="delete-request"]') - .addEventListener('click', (event) => { - Utils.deleteJobRequest(this.userId, this.jobId); - }); this.displayElement .querySelector('.action-button[data-action="get-log-request"]') .addEventListener('click', (event) => { diff --git a/app/static/js/Utils.js b/app/static/js/Utils.js index 88dadea1..1a35acbc 100644 --- a/app/static/js/Utils.js +++ b/app/static/js/Utils.js @@ -493,32 +493,6 @@ class Utils { job = {}; } - let modalElement = Utils.HTMLToElement( - ` - - ` - ); - document.querySelector('#modals').appendChild(modalElement); - let modal = M.Modal.init( - modalElement, - { - dismissible: false, - onCloseEnd: () => { - modal.destroy(); - modalElement.remove(); - } - } - ); - let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { let jobTitle = job?.title; diff --git a/app/templates/_scripts.html.j2 b/app/templates/_scripts.html.j2 index 6fef8d1a..d2cd8fad 100644 --- a/app/templates/_scripts.html.j2 +++ b/app/templates/_scripts.html.j2 @@ -61,7 +61,8 @@ 'js/Requests/contributions/contributions.js', 'js/Requests/contributions/spacy_nlp_pipeline_models.js', 'js/Requests/contributions/tesseract_ocr_pipeline_models.js', - 'js/Requests/Corpora.js' + 'js/Requests/Corpora.js', + 'js/Requests/jobs/jobs.js' %} {%- endassets %} diff --git a/app/templates/jobs/job.html.j2 b/app/templates/jobs/job.html.j2 index c1222127..30bedaa1 100644 --- a/app/templates/jobs/job.html.j2 +++ b/app/templates/jobs/job.html.j2 @@ -79,10 +79,10 @@
{% if current_user.is_administrator() %} - text_snippetLog + text_snippetLog {% endif %} repeatRestart - deleteDelete + deleteDelete
@@ -112,10 +112,42 @@ {% endblock page_content %} +{% block modals %} +{{ super() }} + + + +{% endblock modals %} + {% block scripts %} {{ super() }} {% endblock scripts %}