From 32d1b052c87da51ccbed8241ddb2e45568def0d4 Mon Sep 17 00:00:00 2001 From: Debellis Date: Wed, 13 May 2020 12:43:57 -0700 Subject: [PATCH 01/18] source bashrc in entrypoint --- entrypoint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/entrypoint.sh b/entrypoint.sh index a9527cf0..741e82eb 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -27,5 +27,6 @@ env | grep _ >> /etc/environment # Add conda bin to path export PATH=$PATH:/opt/conda/bin +source /root/.bashrc jupyter lab --ip=0.0.0.0 --port=3100 --allow-root --NotebookApp.token='' --LabApp.base_url=$PREVIEW_URL --no-browser --debug From 85248d862968e56270e886c4ba99bd9d293c443f Mon Sep 17 00:00:00 2001 From: echyam Date: Tue, 19 May 2020 14:25:10 -0700 Subject: [PATCH 02/18] submit jobs request propagate returned error messages --- submit_jobs/src/widgets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submit_jobs/src/widgets.ts b/submit_jobs/src/widgets.ts index ccbe0545..de74e54b 100644 --- a/submit_jobs/src/widgets.ts +++ b/submit_jobs/src/widgets.ts @@ -338,7 +338,7 @@ export class InputWidget extends Widget { // console.log(json_response); me._responseText = me._responseText + '\n' + json_response['result']; } else { - me._responseText = "Error Sending Request."; + me._responseText = "Error Sending Request:\n" + json_response['result']; } console.log("updating"); me.updateSearchResults(); From 019871f9bf4fef9590a3842fd2dae68b7ed86fa9 Mon Sep 17 00:00:00 2001 From: echyam Date: Tue, 19 May 2020 14:38:58 -0700 Subject: [PATCH 03/18] get request response json --- submit_jobs/src/widgets.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/submit_jobs/src/widgets.ts b/submit_jobs/src/widgets.ts index de74e54b..cf0da06a 100644 --- a/submit_jobs/src/widgets.ts +++ b/submit_jobs/src/widgets.ts @@ -338,6 +338,7 @@ export class InputWidget extends Widget { // console.log(json_response); me._responseText = me._responseText + '\n' + json_response['result']; } else { + let json_response:any = res.json(); me._responseText = "Error Sending Request:\n" + json_response['result']; } console.log("updating"); From ea6ddc04a0f42dfac5ccbaa5e1ba40cae076cf59 Mon Sep 17 00:00:00 2001 From: echyam Date: Tue, 19 May 2020 14:57:16 -0700 Subject: [PATCH 04/18] catch nonzero exit subprocess on git status if not register code not in repo --- submit_jobs/submit_jobs/handlers.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 9d948e0c..4bd324c6 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -150,14 +150,20 @@ def get(self,**params): # proj_path = params['config_path'] os.chdir(proj_path) - # get git status - git_status_out = subprocess.check_output("git status --branch --porcelain", shell=True).decode("utf-8") - logger.debug(git_status_out) + try: + # get git status + git_status_out = subprocess.check_output("git status --branch --porcelain", shell=True).decode("utf-8") + logger.debug(git_status_out) - # is there a git repo? - if 'not a git repository' in git_status_out: - self.finish({"status_code": 412, "result": "Error: \n{}".format(git_status_out)}) - return + # is there a git repo? + if 'not a git repository' in git_status_out: + self.finish({"status_code": 412, "result": "Error: \n{}".format(git_status_out)}) + return + + except: + # subprocess could also error out (nonzero exit code) + self.finish({"status_code": 412, "result": "Error: \nThe code you want to register is not saved in a git repository."}) + return git_status = git_status_out.splitlines()[1:] git_status = [e.strip() for e in git_status] From 6339793193c17669ddc27578e324d908a2392f3e Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 20 May 2020 13:29:23 -0700 Subject: [PATCH 05/18] typo --- submit_jobs/submit_jobs/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 4bd324c6..274735fa 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -163,7 +163,7 @@ def get(self,**params): except: # subprocess could also error out (nonzero exit code) self.finish({"status_code": 412, "result": "Error: \nThe code you want to register is not saved in a git repository."}) - return + return git_status = git_status_out.splitlines()[1:] git_status = [e.strip() for e in git_status] From 6dd7397a099c93b9e549668941d0871d0c01f58b Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 20 May 2020 15:52:30 -0700 Subject: [PATCH 06/18] catch subprocess nonzero exit in defaultvalues handler --- submit_jobs/submit_jobs/handlers.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 274735fa..8d9c387a 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -150,16 +150,12 @@ def get(self,**params): # proj_path = params['config_path'] os.chdir(proj_path) + # get git status try: - # get git status git_status_out = subprocess.check_output("git status --branch --porcelain", shell=True).decode("utf-8") logger.debug(git_status_out) - # is there a git repo? - if 'not a git repository' in git_status_out: - self.finish({"status_code": 412, "result": "Error: \n{}".format(git_status_out)}) - return - + # is there a git repo? except: # subprocess could also error out (nonzero exit code) self.finish({"status_code": 412, "result": "Error: \nThe code you want to register is not saved in a git repository."}) @@ -1227,8 +1223,19 @@ def get(self): proj_path = '/projects/'+params['code_path'] proj_path = '/'.join(proj_path.split('/')[:-1]) os.chdir(proj_path) - repo_url = subprocess.check_output("git remote get-url origin", shell=True).decode('utf-8').strip() - # logger.debug(repo_url) + + # try to get git remote url + try: + repo_url = subprocess.check_output("git remote get-url origin", shell=True).decode('utf-8').strip() + logger.debug(repo_url) + print('reop url is {}'.format(repo_url)) + + # is there a git repo? + except: + # subprocess could also error out (nonzero exit code) + self.finish({"status_code": 412, "result": "Error: \nThe code you want to register is not saved in a git repository."}) + return + vals = {} code_path = params['code_path'] From caeeaab008833c22b7c03b0146872cd9723e98b7 Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 20 May 2020 16:49:00 -0700 Subject: [PATCH 07/18] report no git repo error to user --- submit_jobs/src/activate.ts | 78 ++++++++++++++++------------- submit_jobs/submit_jobs/handlers.py | 2 +- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/submit_jobs/src/activate.ts b/submit_jobs/src/activate.ts index 8ed2b4a7..48a27415 100644 --- a/submit_jobs/src/activate.ts +++ b/submit_jobs/src/activate.ts @@ -68,47 +68,53 @@ export function activateRegisterAlgorithm( // send request to defaultvalueshandler let getValuesFn = function(resp:Object) { console.log('getValuesFn'); - let configPath = resp['config_path'] as string; - let defaultValues = resp['default_values'] as Object; - let prevConfig = resp['previous_config'] as boolean; + console.log(resp['status_code']); + if (resp['status_code'] != 200) { + // error + popupText(resp['result'],'Error Registering Algorithm'); + } else { + let configPath = resp['config_path'] as string; + let defaultValues = resp['default_values'] as Object; + let prevConfig = resp['previous_config'] as boolean; - if (defaultValues['inputs'] == undefined) { - defaultValues['inputs'] = []; - } - if (defaultValues['description'] == undefined) { - defaultValues['description'] = ''; - } - - console.log(defaultValues); + if (defaultValues['inputs'] == undefined) { + defaultValues['inputs'] = []; + } + if (defaultValues['description'] == undefined) { + defaultValues['description'] = ''; + } - let subtext = 'Auto-generated algorithm configuration:'; - if (prevConfig) { - subtext = 'Current algorithm configuration:'; - } + console.log(defaultValues); - // register function to be called - // popup read-only default values - let registerfn = function() { - console.log('registerfn testing'); - let w = new RegisterWidget(registerFields,username,defaultValues,subtext,configPath); - w.setPredefinedFields(defaultValues); - console.log(w); - popup(w); - } + let subtext = 'Auto-generated algorithm configuration:'; + if (prevConfig) { + subtext = 'Current algorithm configuration:'; + } - // check if algorithm already exists - // ok -> call registeralgorithmhandler - // cancel -> edit template at algorithm_config.yaml (config_path) - algorithmExists(defaultValues['algo_name'],defaultValues['version'],defaultValues['environment']).then((algoExists) => { - console.log('algo Exists'); - console.log(algoExists); - if (algoExists != undefined && algoExists) { - popupText('WARNING Algorithm name and version already exists. \n If you continue, the previously registered algorithm \nwill be LOST','Overwrite Algorithm?',registerfn); - // ask user if they want to continue - } else { - registerfn() + // register function to be called + // popup read-only default values + let registerfn = function() { + console.log('registerfn testing'); + let w = new RegisterWidget(registerFields,username,defaultValues,subtext,configPath); + w.setPredefinedFields(defaultValues); + console.log(w); + popup(w); } - }); + + // check if algorithm already exists + // ok -> call registeralgorithmhandler + // cancel -> edit template at algorithm_config.yaml (config_path) + algorithmExists(defaultValues['algo_name'],defaultValues['version'],defaultValues['environment']).then((algoExists) => { + console.log('algo Exists'); + console.log(algoExists); + if (algoExists != undefined && algoExists) { + popupText('WARNING Algorithm name and version already exists. \n If you continue, the previously registered algorithm \nwill be LOST','Overwrite Algorithm?',registerfn); + // ask user if they want to continue + } else { + registerfn() + } + }); + } }; inputRequest('defaultValues','Register Algorithm',{'code_path':path},getValuesFn); }, diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 8d9c387a..2b32b95c 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -1278,7 +1278,7 @@ def get(self): logger.debug(settings) # outputs: algo_name, version, environment, repository_url, dockerfile_path - self.finish({"status_code": 200, "default_values":settings, "config_path":config_path, "previous_config":prev_config}) + self.finish({"status_code": 200, "result": "Got default values.", "default_values":settings, "config_path":config_path, "previous_config":prev_config}) class ListJobsHandler(IPythonHandler): # inputs: username From 1f9cd079e07a4e63aefda34ee48b5f1d589eea2d Mon Sep 17 00:00:00 2001 From: echyam Date: Thu, 21 May 2020 10:59:49 -0700 Subject: [PATCH 08/18] don't convert inputs to lower case --- submit_jobs/src/funcs.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/submit_jobs/src/funcs.ts b/submit_jobs/src/funcs.ts index 5087fc62..cf859ed9 100644 --- a/submit_jobs/src/funcs.ts +++ b/submit_jobs/src/funcs.ts @@ -49,10 +49,8 @@ export function inputRequest(endpt:string,title:string,inputs:{[k:string]:string // add params for (let key in inputs) { var fieldValue = inputs[key]; - - if(key !== 'proxy-ticket') - fieldValue = fieldValue.toLowerCase(); - + // if(key !== 'proxy-ticket') + // fieldValue = fieldValue.toLowerCase(); requestUrl.searchParams.append(key.toLowerCase(), fieldValue); } console.log(requestUrl.href); From 6e09a7f551504a4305f6ae1a6cbd3891bdc59b08 Mon Sep 17 00:00:00 2001 From: echyam Date: Thu, 21 May 2020 11:23:54 -0700 Subject: [PATCH 09/18] register algo config req params check for none --- submit_jobs/submit_jobs/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 2b32b95c..633bf516 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -123,7 +123,7 @@ def get(self,**params): # only description and inputs are allowed to be empty for f in ['algo_name','version','environment','run_command','repository_url','docker_url']: - if config[f] == '': + if config[f] == '' or config[f] == None: self.finish({"status_code": 412, "result": "Error: Register field {} cannot be empty".format(f)}) return From e0e4b2c6d7b5e128c15b58e2bb254579a9e77dfe Mon Sep 17 00:00:00 2001 From: echyam Date: Thu, 21 May 2020 12:17:17 -0700 Subject: [PATCH 10/18] register commit check for r and matlab file exts --- submit_jobs/submit_jobs/handlers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/submit_jobs/submit_jobs/handlers.py b/submit_jobs/submit_jobs/handlers.py index 633bf516..df28fab8 100644 --- a/submit_jobs/submit_jobs/handlers.py +++ b/submit_jobs/submit_jobs/handlers.py @@ -164,8 +164,8 @@ def get(self,**params): git_status = git_status_out.splitlines()[1:] git_status = [e.strip() for e in git_status] - # filter for unsaved python files - unsaved = list(filter(lambda e: ( (e.split('.')[-1] in ['ipynb','py','sh','jl']) and (e[0] in ['M','?']) ), git_status)) + # filter for unsaved python, julia, matlab shell files + unsaved = list(filter(lambda e: ( (e.split('.')[-1] in ['ipynb','py','sh','jl','r','m','mat']) and (e[0] in ['M','?']) ), git_status)) if len(unsaved) != 0: self.finish({"status_code": 412, "result": "Error: Notebook(s) and/or script(s) have not been committed\n{}".format('\n'.join(unsaved))}) return From bacc43a497c10d646895a3ab082bab503ddc22bc Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 18 Mar 2020 13:52:14 -0700 Subject: [PATCH 11/18] update architecture docs for submit jobs, add for dps info --- dps_info/documentation.md | 15 +++++++++++++++ dps_info/dps_info_architecture.png | Bin 0 -> 11070 bytes submit_jobs/documentation.md | 9 ++------- submit_jobs/submit_jobs_architecture.png | Bin 19011 -> 16344 bytes 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 dps_info/documentation.md create mode 100644 dps_info/dps_info_architecture.png diff --git a/dps_info/documentation.md b/dps_info/documentation.md new file mode 100644 index 00000000..175b2e76 --- /dev/null +++ b/dps_info/documentation.md @@ -0,0 +1,15 @@ +## DPS Info Extension Documentation & Architecture +### Architecture +architecture diagram + +#### sourcefiles +- index.ts: instantiate & export jupyter extensions +- activate.ts: contains all extension activate functions +- panel.ts: contains skeleton code for a basic side panel in jupyter lab, wth a commented-out example activate function (extension must be instantiated and exported as well) +- jobinfo.ts: 1) creates a widget for listing DPS jobs associated with the user in table; 2) creates a main area jupyter widget for easy UI in listing, describing, and executing algorithms; (1) and (2) are NOT synchronized; the table in (1) is organized as: + +| Job Id | Status | Algorithm | +| ------ | ------ | --------- | + +- funcs.ts: common functions across classes & API calls in jobinfo.ts +- request.ts: class and functions utility for making http requests and reading their responses diff --git a/dps_info/dps_info_architecture.png b/dps_info/dps_info_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..a31d99d58a83107d5796d90b4c96b04041db71f4 GIT binary patch literal 11070 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 literal 19011 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 Date: Tue, 26 May 2020 11:09:09 -0700 Subject: [PATCH 12/18] add toastify error on register responses --- submit_jobs/src/widgets.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/submit_jobs/src/widgets.ts b/submit_jobs/src/widgets.ts index cf0da06a..b75ab509 100644 --- a/submit_jobs/src/widgets.ts +++ b/submit_jobs/src/widgets.ts @@ -340,6 +340,7 @@ export class InputWidget extends Widget { } else { let json_response:any = res.json(); me._responseText = "Error Sending Request:\n" + json_response['result']; + INotification.error(me._responseText); } console.log("updating"); me.updateSearchResults(); From 7ad291235ee14ede7f01dd2886f77f34bbadf33b Mon Sep 17 00:00:00 2001 From: echyam Date: Tue, 26 May 2020 11:54:15 -0700 Subject: [PATCH 13/18] toastify error for other submit jobs requests --- submit_jobs/src/funcs.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/submit_jobs/src/funcs.ts b/submit_jobs/src/funcs.ts index cf859ed9..80f4b3e5 100644 --- a/submit_jobs/src/funcs.ts +++ b/submit_jobs/src/funcs.ts @@ -68,6 +68,9 @@ export function inputRequest(endpt:string,title:string,inputs:{[k:string]:string console.log('fn defined'); fn(json_response); } + } else { + var json_response:any = res.json(); + INotification.error(json_response['result']); } }); } From 0141a22e5ee866dd06daff69997a5762c5e9ee59 Mon Sep 17 00:00:00 2001 From: echyam Date: Tue, 26 May 2020 12:03:50 -0700 Subject: [PATCH 14/18] dependency --- submit_jobs/src/funcs.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/submit_jobs/src/funcs.ts b/submit_jobs/src/funcs.ts index 80f4b3e5..03fd1bbe 100644 --- a/submit_jobs/src/funcs.ts +++ b/submit_jobs/src/funcs.ts @@ -1,4 +1,5 @@ import { PageConfig } from '@jupyterlab/coreutils' +import { INotification } from 'jupyterlab_toastify'; import { request, RequestResult } from './request'; import { popupResultText } from './widgets'; From 66a2614f32d0f0641a6a3c69e3624020322c7006 Mon Sep 17 00:00:00 2001 From: Debellis Date: Tue, 26 May 2020 16:02:21 -0700 Subject: [PATCH 15/18] copy bashrc to bash_profile in entrypoint --- entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entrypoint.sh b/entrypoint.sh index 741e82eb..a076630a 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -27,6 +27,6 @@ env | grep _ >> /etc/environment # Add conda bin to path export PATH=$PATH:/opt/conda/bin -source /root/.bashrc +cp /root/.bashrc ~/.bash_profile jupyter lab --ip=0.0.0.0 --port=3100 --allow-root --NotebookApp.token='' --LabApp.base_url=$PREVIEW_URL --no-browser --debug From f7231d5b3efe34d5c532661740627d48d900cade Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 27 May 2020 11:11:55 -0700 Subject: [PATCH 16/18] add toastify error for default vals in register --- submit_jobs/src/activate.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/submit_jobs/src/activate.ts b/submit_jobs/src/activate.ts index 48a27415..2c2350cd 100644 --- a/submit_jobs/src/activate.ts +++ b/submit_jobs/src/activate.ts @@ -4,6 +4,7 @@ import { ILauncher } from '@jupyterlab/launcher'; import { IFileBrowserFactory } from "@jupyterlab/filebrowser"; import { IMainMenu } from '@jupyterlab/mainmenu'; import { Menu } from '@phosphor/widgets'; +import { INotification } from 'jupyterlab_toastify'; import { InputWidget, RegisterWidget, popupText } from './widgets'; import { ProjectSelector } from './selector'; import { popup, popupResult } from './dialogs'; @@ -72,6 +73,7 @@ export function activateRegisterAlgorithm( if (resp['status_code'] != 200) { // error popupText(resp['result'],'Error Registering Algorithm'); + INotification.error(resp['result']); } else { let configPath = resp['config_path'] as string; let defaultValues = resp['default_values'] as Object; From 7f38f9148e700414674ad6725ab0d8f28215241a Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 27 May 2020 12:02:08 -0700 Subject: [PATCH 17/18] testing register result --- submit_jobs/src/widgets.ts | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/submit_jobs/src/widgets.ts b/submit_jobs/src/widgets.ts index b75ab509..b744f540 100644 --- a/submit_jobs/src/widgets.ts +++ b/submit_jobs/src/widgets.ts @@ -335,10 +335,11 @@ export class InputWidget extends Widget { request('get', getUrl.href).then((res: RequestResult) => { if(res.ok){ let json_response:any = res.json(); - // console.log(json_response); + console.log(json_response); me._responseText = me._responseText + '\n' + json_response['result']; } else { let json_response:any = res.json(); + console.log(json_response); me._responseText = "Error Sending Request:\n" + json_response['result']; INotification.error(me._responseText); } @@ -384,13 +385,13 @@ export class RegisterWidget extends InputWidget { subtxt.style.flexDirection = 'column'; subtxt.innerHTML = subtext; this.node.appendChild(subtxt); - this.node.appendChild(document.createElement("BR")); + this.node.appendChild(document.createElement('BR')); } for (var field of this.fields) { // textarea for inputs field in register - if (field == "inputs") { - var fieldLabel = document.createElement("Label"); + if (field == 'inputs') { + var fieldLabel = document.createElement('Label'); fieldLabel.innerHTML = field; this.node.appendChild(fieldLabel); @@ -415,7 +416,7 @@ export class RegisterWidget extends InputWidget { this.node.appendChild(fieldInputs); } else { - var fieldLabel = document.createElement("Label"); + var fieldLabel = document.createElement('Label'); fieldLabel.innerHTML = field; this.node.appendChild(fieldLabel); @@ -431,7 +432,7 @@ export class RegisterWidget extends InputWidget { } // BREAK - var x = document.createElement("BR"); + var x = document.createElement('BR'); this.node.appendChild(x) // footer text - edit config at path @@ -498,7 +499,7 @@ export class WidgetResult extends Widget { // update panel text on resolution of result popup getValue() { console.log('checking popup resolution fn'); - if (this.okfn != undefined) { + if (typeof this.okfn === "function") { console.log(this.okfn); try{ this.okfn(); @@ -517,18 +518,18 @@ export function popupResultText(result:string,title:string,fn?:any,isXML?:boolea body.style.display = 'flex'; body.style.flexDirection = 'column'; - var textarea = document.createElement("div"); + var textarea = document.createElement('div'); textarea.id = 'result-text'; textarea.style.display = 'flex'; textarea.style.flexDirection = 'column'; var format = require('xml-formatter'); // console.log(result); - if ( isXML == undefined || (! isXML) ){ - textarea.innerHTML = "

" + result + "
"; + if ( isXML === undefined || (! isXML) ){ + textarea.innerHTML = '
' + result + '
'; // console.log(textarea); } else { - var xml = "

"+result+"

"; + var xml = '

'+result+'

'; var options = {indentation: ' ', stripComments: true, collapseContent: false}; var formattedXML = format(xml,options); textarea.innerHTML = formattedXML; @@ -545,16 +546,16 @@ export function popupText(result:string,title:string,fn?:any) { body.style.display = 'flex'; body.style.flexDirection = 'column'; - var textarea = document.createElement("div"); + var textarea = document.createElement('div'); textarea.id = 'result-text'; textarea.style.display = 'flex'; textarea.style.flexDirection = 'column'; // console.log(result); - textarea.innerHTML = "
" + result + "
"; + textarea.innerHTML = '
' + result + '
'; body.appendChild(textarea); // console.log(body); - if (fn == undefined) { + if (fn === undefined) { popupTitle(new Widget({node:body}),title); } else { popupTitle(new WidgetResult(body,fn),title); From 34f5e34e6488f1299f4984f677d5950c138d23ff Mon Sep 17 00:00:00 2001 From: echyam Date: Wed, 27 May 2020 12:23:19 -0700 Subject: [PATCH 18/18] more register toastify errors --- submit_jobs/src/widgets.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/submit_jobs/src/widgets.ts b/submit_jobs/src/widgets.ts index b744f540..b933e70b 100644 --- a/submit_jobs/src/widgets.ts +++ b/submit_jobs/src/widgets.ts @@ -335,11 +335,14 @@ export class InputWidget extends Widget { request('get', getUrl.href).then((res: RequestResult) => { if(res.ok){ let json_response:any = res.json(); - console.log(json_response); + // console.log(json_response); me._responseText = me._responseText + '\n' + json_response['result']; + if (json_response['status_code'] != 200) { + INotification.error(me._responseText); + } } else { let json_response:any = res.json(); - console.log(json_response); + // console.log(json_response); me._responseText = "Error Sending Request:\n" + json_response['result']; INotification.error(me._responseText); }