From ecea33ffa9dc70aec10db7dd60c517a9ee8ff5b2 Mon Sep 17 00:00:00 2001 From: Patrick Jentsch <p.jentsch@uni-bielefeld.de> Date: Mon, 9 Jan 2023 10:03:52 +0100 Subject: [PATCH] Make Utils functions more stable --- app/static/js/Utils.js | 147 +++++++++++++++++++++++++++-------------- 1 file changed, 97 insertions(+), 50 deletions(-) diff --git a/app/static/js/Utils.js b/app/static/js/Utils.js index e7b4aa1b..2b81a8ed 100644 --- a/app/static/js/Utils.js +++ b/app/static/js/Utils.js @@ -5,10 +5,10 @@ class Utils { return tmpElement.firstChild; } - static generateElementId(prefix='') { + static generateElementId(prefix='', suffix='') { for (let i = 0; true; i++) { - if (document.querySelector(`#${prefix}${i}`) !== null) {continue;} - return `${prefix}${i}`; + if (document.querySelector(`#${prefix}${i}${suffix}`) !== null) {continue;} + return `${prefix}${i}${suffix}`; } } @@ -21,15 +21,11 @@ class Utils { if (objects.length === 0) { return mergedObject; } + if (!Utils.isObject(objects[0])) {throw 'Cannot merge non-object';} if (objects.length === 1) { - if (!Utils.isObject(objects[0])) { - throw 'Cannot merge non-object'; - } return Utils.mergeObjectsDeep(mergedObject, objects[0]); } - if (!Utils.isObject(objects[0]) || !Utils.isObject(objects[1])) { - throw 'Cannot merge non-object'; - } + if (!Utils.isObject(objects[1])) {throw 'Cannot merge non-object';} for (let key in objects[0]) { if (objects[0].hasOwnProperty(key)) { if (objects[1].hasOwnProperty(key)) { @@ -58,15 +54,20 @@ class Utils { static buildCorpusRequest(userId, corpusId) { return new Promise((resolve, reject) => { - let corpus = app.data.users[userId].corpora[corpusId]; + let corpus; + try { + corpus = app.data.users[userId].corpora[corpusId]; + } catch (error) { + corpus = {}; + } - fetch(`/corpora/${corpus.id}/build`, {method: 'POST', headers: {Accept: 'application/json'}}) + fetch(`/corpora/${corpusId}/build`, {method: 'POST', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);} if (response.status === 409) {app.flash('Conflict', 'error'); reject(response);} - app.flash(`Corpus "${corpus.title}" marked for building`, 'corpus'); + app.flash(`Corpus "${corpus?.title}" marked for building`, 'corpus'); resolve(response); }, (response) => { @@ -79,14 +80,19 @@ class Utils { static deleteCorpusRequest(userId, corpusId) { return new Promise((resolve, reject) => { - let corpus = app.data.users[userId].corpora[corpusId]; + let corpus; + try { + corpus = app.data.users[userId].corpora[corpusId]; + } catch (error) { + corpus = {}; + } let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm Corpus deletion</h4> - <p>Do you really want to delete the Corpus <b>${corpus.title}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the Corpus <b>${corpus?.title}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -109,13 +115,13 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let corpusTitle = corpus.title; - fetch(`/corpora/${corpus.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) + let corpusTitle = corpus?.title; + fetch(`/corpora/${corpusId}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);} - app.flash(`Corpus "${corpus.title}" marked for deletion`, 'corpus'); + app.flash(`Corpus "${corpusTitle}" marked for deletion`, 'corpus'); resolve(response); }, (response) => { @@ -130,15 +136,19 @@ class Utils { static deleteCorpusFileRequest(userId, corpusId, corpusFileId) { return new Promise((resolve, reject) => { - let corpus = app.data.users[userId].corpora[corpusId]; - let corpusFile = corpus.files[corpusFileId]; + let corpusFile; + try { + corpusFile = app.data.users[userId].corpora[corpusId].files[corpusFileId]; + } catch (error) { + corpusFile = {}; + } let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm Corpus File deletion</h4> - <p>Do you really want to delete the Corpus File <b>${corpusFile.title}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the Corpus File <b>${corpusFile?.title}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -161,7 +171,7 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let corpusFileTitle = corpusFile.title; + let corpusFileTitle = corpusFile?.title; fetch(`/corpora/${corpusId}/files/${corpusFileId}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) .then( (response) => { @@ -182,13 +192,19 @@ class Utils { static deleteSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId) { return new Promise((resolve, reject) => { - let spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId]; + let spaCyNLPPipelineModel; + try { + spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId]; + } catch (error) { + spaCyNLPPipelineModel = {}; + } + let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm SpaCy NLP Pipeline Model deletion</h4> - <p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${spaCyNLPPipelineModel.title}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${spaCyNLPPipelineModel?.title}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -210,7 +226,7 @@ class Utils { ); let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let spaCyNLPPipelineModelTitle = spaCyNLPPipelineModel.title; + let spaCyNLPPipelineModelTitle = spaCyNLPPipelineModel?.title; fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}`, {method: 'DELETE'}) .then( (response) => { @@ -231,13 +247,19 @@ class Utils { static deleteTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId) { return new Promise((resolve, reject) => { - let tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId]; + let tesseractOCRPipelineModel; + try { + tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId]; + } catch (error) { + tesseractOCRPipelineModel = {}; + } + let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm Tesseract OCR Pipeline Model deletion</h4> - <p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${tesseractOCRPipelineModel.title}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${tesseractOCRPipelineModel?.title}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -259,7 +281,7 @@ class Utils { ); let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let tesseractOCRPipelineModelTitle = tesseractOCRPipelineModel.title; + let tesseractOCRPipelineModelTitle = tesseractOCRPipelineModel?.title; fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}`, {method: 'DELETE'}) .then( (response) => { @@ -328,14 +350,19 @@ class Utils { static deleteJobRequest(userId, jobId) { return new Promise((resolve, reject) => { - let job = app.data.users[userId].jobs[jobId]; + let job; + try { + job = app.data.users[userId].jobs[jobId]; + } catch (error) { + job = {}; + } let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm Job deletion</h4> - <p>Do you really want to delete the Job <b>${job.title}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the Job <b>${job?.title}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -358,8 +385,8 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let jobTitle = job.title; - fetch(`/jobs/${job.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) + let jobTitle = job?.title; + fetch(`/jobs/${jobId}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} @@ -379,9 +406,7 @@ class Utils { static getJobLogRequest(userId, jobId) { return new Promise((resolve, reject) => { - let job = app.data.users[userId].jobs[jobId]; - - fetch(`/jobs/${job.id}/log`, {method: 'GET', headers: {Accept: 'application/json, text/plain'}}) + fetch(`/jobs/${jobId}/log`, {method: 'GET', headers: {Accept: 'application/json, text/plain'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} @@ -427,14 +452,19 @@ class Utils { static restartJobRequest(userId, jobId) { return new Promise((resolve, reject) => { - let job = app.data.users[userId].jobs[jobId]; + let job; + try { + job = app.data.users[userId].jobs[jobId]; + } catch (error) { + job = {}; + } let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm Job restart</h4> - <p>Do you really want to restart the Job <b>${job.title}</b>? All Job Results will be permanently deleted.</p> + <p>Do you really want to restart the Job <b>${job?.title}</b>? All Job Results will be permanently deleted.</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -457,8 +487,8 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let jobTitle = job.title; - fetch(`/jobs/${job.id}/restart`, {method: 'POST', headers: {Accept: 'application/json'}}) + let jobTitle = job?.title; + fetch(`/jobs/${jobId}/restart`, {method: 'POST', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} @@ -479,14 +509,19 @@ class Utils { static deleteUserRequest(userId) { return new Promise((resolve, reject) => { - let user = app.data.users[userId]; + let user; + try { + user = app.data.users[userId]; + } catch (error) { + user = {}; + } let modalElement = Utils.elementFromString( ` <div class="modal"> <div class="modal-content"> <h4>Confirm User deletion</h4> - <p>Do you really want to delete the User <b>${user.username}</b>? All files will be permanently deleted!</p> + <p>Do you really want to delete the User <b>${user?.username}</b>? All files will be permanently deleted!</p> </div> <div class="modal-footer"> <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a> @@ -509,8 +544,8 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - let userName = user.username; - fetch(`/users/${user.id}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) + let userName = user?.username; + fetch(`/users/${userId}`, {method: 'DELETE', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} @@ -530,14 +565,20 @@ class Utils { static shareTesseractOCRPipelineModelRequest(userId, tesseractOCRPipelineModelId, is_public) { return new Promise((resolve, reject) => { - let tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId]; + let tesseractOCRPipelineModel; + try { + tesseractOCRPipelineModel = app.data.users[userId].tesseract_ocr_pipeline_models[tesseractOCRPipelineModelId]; + } catch (error) { + tesseractOCRPipelineModel = {}; + } + let msg = ''; if (is_public) { - msg = `Model "${tesseractOCRPipelineModel.title}" is now public`; + msg = `Model "${tesseractOCRPipelineModel?.title}" is now public`; } else { - msg = `Model "${tesseractOCRPipelineModel.title}" is now private`; + msg = `Model "${tesseractOCRPipelineModel?.title}" is now private`; } - fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}}) + fetch(`/contributions/tesseract-ocr-pipeline-models/${tesseractOCRPipelineModelId}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} @@ -554,14 +595,20 @@ class Utils { static shareSpaCyNLPPipelineModelRequest(userId, spaCyNLPPipelineModelId, is_public) { return new Promise((resolve, reject) => { - let spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId]; + let spaCyNLPPipelineModel; + try { + spaCyNLPPipelineModel = app.data.users[userId].spacy_nlp_pipeline_models[spaCyNLPPipelineModelId]; + } catch (error) { + spaCyNLPPipelineModel = {}; + } + let msg = ''; if (is_public) { - msg = `Model "${spaCyNLPPipelineModel.title}" is now public`; + msg = `Model "${spaCyNLPPipelineModel?.title}" is now public`; } else { - msg = `Model "${spaCyNLPPipelineModel.title}" is now private`; + msg = `Model "${spaCyNLPPipelineModel?.title}" is now private`; } - fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModel.id}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}}) + fetch(`/contributions/spacy-nlp-pipeline-models/${spaCyNLPPipelineModelId}/toggle-public-status`, {method: 'POST', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} -- GitLab