From 05682f5aa20b8073fef6b775903a05bbf75c2882 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Thu, 15 Feb 2024 20:02:15 +0000 Subject: [PATCH 1/7] Fix version --- app/assets/javascripts/3dbio_viewer/public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/3dbio_viewer/public/index.html b/app/assets/javascripts/3dbio_viewer/public/index.html index 7fec5dcd..5a4a50a1 100644 --- a/app/assets/javascripts/3dbio_viewer/public/index.html +++ b/app/assets/javascripts/3dbio_viewer/public/index.html @@ -17,8 +17,8 @@ type="text/css" /> - - + + 3dbio Viewer From 997887bf18ba93b353af01f860dd467176fc6294 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Thu, 15 Feb 2024 20:15:32 +0000 Subject: [PATCH 2/7] Error 503 difference between 404 --- .../molecular-structure/usePdbPlugin.ts | 117 ++++++++++++------ .../molecular-structure/usePluginRef.ts | 7 +- 2 files changed, 80 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePdbPlugin.ts b/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePdbPlugin.ts index dec1f132..da4e40f6 100644 --- a/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePdbPlugin.ts +++ b/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePdbPlugin.ts @@ -52,6 +52,7 @@ export const loaderErrors = { unexpectedUploadError: (url: string) => i18n.t(`Unkown error while loading the model URL: ${url}`), modelNotFound: (pdbId: string) => i18n.t(`${pdbId} was not found`), + serviceUnavailable: (pdbId: string) => i18n.t(`Unable to load ${pdbId}. Service unavailable`), pdbRequest: (url: string, status: number) => i18n.t(`Error loading PDB model: url=${url} - ${status}`), request: (url: string, status: number) => i18n.t(`Error loading model: url=${url} - ${status}`), @@ -136,18 +137,20 @@ export function usePdbePlugin(options: MolecularStructureProps) { newSelection.type === "free" ? Promise.all( newSelection.refinedModels.map( - async m => - await checkModelUrl(getRefinedModelId(m), m.type).then(loaded => { - if (loaded) return m; - else { - pdbePlugin.canvas.showToast({ - title: i18n.t("Error"), - message: loaderErrors.modelNotFound(m.id), - key: errorsKeys.modelNotFound, - }); - return undefined; + async model => + await checkModelUrl(getRefinedModelId(model), model.type).then( + res => { + if (res.loaded) return model; + else { + pdbePlugin.canvas.showToast({ + title: i18n.t("Error"), + message: getErrorByStatus(model.id, res.status), + key: errorKeyByStatus(res.status), + }); + return undefined; + } } - }) + ) ) ).then(models => _.compact(models)) : Promise.resolve([]); @@ -241,8 +244,8 @@ export function usePdbePlugin(options: MolecularStructureProps) { loaderKeys.uploadedModel, new Promise((resolve, reject) => { checkUploadedModelUrl(uploadUrl) - .then(result => { - if (result) { + .then(res => { + if (res.loaded) { pdbePlugin.events.loadComplete.subscribe({ next: loaded => { console.debug("molstar.events.loadComplete", loaded); @@ -353,8 +356,8 @@ export async function applySelectionChangesToPlugin( const item = items[i]; if (item) { const id: string = getRefinedModelId(item); - await checkModelUrl(id, item.type).then(async loaded => { - if (loaded) { + await checkModelUrl(id, item.type).then(async res => { + if (res.loaded) { const url = urls[item.type](id); const loadParams: LoadParams = { url, @@ -373,8 +376,8 @@ export async function applySelectionChangesToPlugin( } else plugin.canvas.showToast({ title: i18n.t("Error"), - message: loaderErrors.modelNotFound(id), - key: errorsKeys.modelNotFound, + message: getErrorByStatus(id, res.status), + key: errorKeyByStatus(res.status), }); }); } @@ -425,8 +428,8 @@ export async function applySelectionChangesToPlugin( const item = pdbs[i]; if (item) { const pdbId = item.id; - await checkModelUrl(pdbId, "pdb").then(async loaded => { - if (loaded) { + await checkModelUrl(pdbId, "pdb").then(async res => { + if (res.loaded) { const url = urls.pdb(pdbId); const loadParams: LoadParams = { url, @@ -445,12 +448,12 @@ export async function applySelectionChangesToPlugin( setVisibility(plugin, item); updateItems(item); } else if (getMainItem(newSelection, "pdb") === pdbId) - updateLoader("loadModel", Promise.reject(loaderErrors.modelNotFound(pdbId))); - if (!loaded) + updateLoader("loadModel", Promise.reject(getErrorByStatus(pdbId, res.status))); + if (!res.loaded) plugin.canvas.showToast({ title: i18n.t("Error"), - message: loaderErrors.modelNotFound(pdbId), - key: errorsKeys.modelNotFound, + message: getErrorByStatus(pdbId, res.status), + key: errorKeyByStatus(res.status), }); }); } @@ -460,8 +463,8 @@ export async function applySelectionChangesToPlugin( const item = emdbs[i]; if (item) { const emdbId = item.id; - await checkModelUrl(emdbId, "emdb").then(async loaded => { - if (loaded) { + await checkModelUrl(emdbId, "emdb").then(async res => { + if (res.loaded) { await updateLoader( "loadModel", loadEmdb(plugin, urls.emdb(item.id)), @@ -475,8 +478,8 @@ export async function applySelectionChangesToPlugin( } else plugin.canvas.showToast({ title: i18n.t("Error"), - message: loaderErrors.modelNotFound(emdbId), - key: errorsKeys.modelNotFound, + message: getErrorByStatus(emdbId, res.status), + key: errorKeyByStatus(res.status), }); }); } @@ -545,29 +548,61 @@ function getId(obj: T): string { return obj.id; } -export async function checkModelUrl(id: Maybe, modelType: Type): Promise { - if (!id) return false; +export async function checkModelUrl(id: Maybe, modelType: Type): Promise { + if (!id) return { loaded: true, status: 404 }; const url = urls[modelType](id); //method HEAD makes 404 be 200 anyways - const res = await fetch(url, { method: "GET", cache: "force-cache" }); //we are only caching if url exist - - if (res.ok && res.status != 404 && res.status != 500) { - return true; - } else { - const msg = loaderErrors.pdbRequest(url, res.status); - console.error(msg); - return false; - } + return await fetch(url, { method: "GET", cache: "force-cache" }) + .then(res => { + console.debug("Checking model: " + id, res.status); + return res.ok + ? { loaded: true, status: res.status } + : { loaded: false, status: res.status }; + }) + .catch(res => { + const msg = loaderErrors.pdbRequest(url, res.status); + console.error(msg); + return { loaded: false, status: res.status }; + }); //we are only caching if url exist } -export async function checkUploadedModelUrl(url: string): Promise { +export async function checkUploadedModelUrl(url: string): Promise { return fetch(url, { method: "HEAD", cache: "force-cache" }).then(res => { - if (res.ok && res.status != 404 && res.status != 500) return true; + if (res.ok && res.status != 404 && res.status != 500 && res.status != 503) + return { loaded: true, status: res.status }; else { const msg = loaderErrors.request(url, res.status); console.error(msg); - return false; + return { loaded: false, status: res.status }; } }); } + +export function getErrorByStatus(id: string, status: number) { + switch (status) { + case 404: + return loaderErrors.modelNotFound(id); + case 500: + return loaderErrors.serviceUnavailable(id); + case 503: + return loaderErrors.serviceUnavailable(id); + default: + return loaderErrors.modelNotFound(id); + } +} + +function errorKeyByStatus(status: number) { + switch (status) { + case 404: + return errorsKeys.modelNotFound; + case 500: + return errorsKeys.serviceUnavailable; + case 503: + return errorsKeys.serviceUnavailable; + default: + return errorsKeys.modelNotFound; + } +} + +type Response = { loaded: boolean; status: number }; diff --git a/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePluginRef.ts b/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePluginRef.ts index f07615be..5e48ecb2 100644 --- a/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePluginRef.ts +++ b/app/assets/javascripts/3dbio_viewer/src/webapp/components/molecular-structure/usePluginRef.ts @@ -7,6 +7,7 @@ import { applySelectionChangesToPlugin, checkModelUrl, checkUploadedModelUrl, + getErrorByStatus, getLigandView, loaderErrors, } from "./usePdbPlugin"; @@ -164,14 +165,14 @@ export function usePluginRef(options: Options) { function loadFromPdb(pdbId: string, element: HTMLDivElement) { checkModelUrl(pdbId, "pdb") - .then(loaded => { - if (loaded) { + .then(res => { + if (res.loaded) { plugin.render(element, initParams); molstarState.current = MolstarStateActions.fromInitParams( initParams, newSelection ); - } else loadVoidMolstar(loaderErrors.modelNotFound(pdbId)); + } else loadVoidMolstar(getErrorByStatus(pdbId, res.status)); }) .catch(err => loadVoidMolstar(err)); } From 715b25ff534c54d092dcaf6d802648cc2207a1d2 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Thu, 15 Feb 2024 20:25:31 +0000 Subject: [PATCH 3/7] Highlight errors --- .../3dbio_viewer/src/webapp/pages/app/App.css | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css b/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css index 8e28a444..66754027 100644 --- a/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css +++ b/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css @@ -165,3 +165,23 @@ header { font-size: 2rem; color: #123546; } + +.msp-plugin .msp-toast-container .msp-toast-entry { + font-size: 1.2em; + background: #f6d6d6; + border: 1px solid #f15151; +} + +.msp-plugin .msp-toast-container .msp-toast-entry .msp-toast-title { + background: #ffa7a7; + padding: 0.25em 0.75em; +} + +.msp-plugin .msp-toast-container .msp-toast-entry .msp-toast-message { + padding: 0.25em 2.5em 0.25em 0.75em; +} + +.msp-plugin .msp-toast-container .msp-toast-entry .msp-material-icon svg { + color: #913131; + margin-bottom: 0; +} From 4f6e93f6631d68285de32287bccef7e903bb7510 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Thu, 15 Feb 2024 20:57:56 +0000 Subject: [PATCH 4/7] Firefox fix inputs width --- .../javascripts/3dbio_viewer/src/webapp/pages/app/App.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css b/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css index 66754027..a2bc9fa9 100644 --- a/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css +++ b/app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css @@ -185,3 +185,7 @@ header { color: #913131; margin-bottom: 0; } + +.rangeForm .inputs input { + width: 70px; +} From eee34f3166ad6aabc48a9b66d03d963fea293187 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Fri, 16 Feb 2024 12:12:20 +0000 Subject: [PATCH 5/7] bump version --- README.md | 2 +- app/assets/javascripts/3dbio_viewer/package.json | 2 +- app/assets/javascripts/covid19/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c003f453..e4f61c37 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 3DBIONOTES-WS v3.10.0 +# 3DBIONOTES-WS v3.10.1 ## Integrating molecular biology diff --git a/app/assets/javascripts/3dbio_viewer/package.json b/app/assets/javascripts/3dbio_viewer/package.json index 1792b951..82fcc489 100644 --- a/app/assets/javascripts/3dbio_viewer/package.json +++ b/app/assets/javascripts/3dbio_viewer/package.json @@ -1,6 +1,6 @@ { "name": "3dbio-viewer", - "version": "3.10.0", + "version": "3.10.1", "private": true, "dependencies": { "@3dbionotes/pdbe-molstar": "3.1.0-est-2", diff --git a/app/assets/javascripts/covid19/package.json b/app/assets/javascripts/covid19/package.json index 567b1807..7bd5085a 100644 --- a/app/assets/javascripts/covid19/package.json +++ b/app/assets/javascripts/covid19/package.json @@ -1,7 +1,7 @@ { "name": "covid19", "description": "3dbionotes COVID-19", - "version": "3.10.0", + "version": "3.10.1", "homepage": ".", "dependencies": { "@dhis2/d2-i18n": "1.0.6", From 9aa4d0d77c87d7397be23bcdb838f361cb61f5f1 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Tue, 20 Feb 2024 16:43:11 +0000 Subject: [PATCH 6/7] Add PDB on entries with EMD (carousel) --- app/models/covid19.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/covid19.rb b/app/models/covid19.rb index ff7bd7c0..d902b5fc 100644 --- a/app/models/covid19.rb +++ b/app/models/covid19.rb @@ -11,7 +11,7 @@ def self.selected_entries name: "7MSW + EMD-23970", description: "NSP2: Although its function is still unknown, NSP2 has been involved in several viral processes. Its highly-conserved Zn2+ binding site suggests that nsp2 binds RNA. It also seems to interact with host infected cell endosomes through cytoskeletal elements and with modulators of translation. ", image_url: "images/entries/7msw.png", - query_url: "/ws/viewer/#/EMD-23970" + query_url: "/ws/viewer/#/7msw+EMD-23970" }, { name: "7TI9", @@ -59,7 +59,7 @@ def self.selected_entries name: "7C2K + EMD-30275", description: "NSP7: As cofactor of NSP12, NSP7 contributes to accomodate the template-product RNA, together with NSP8, in the RNA-dependent RNA polymerase (RdRp) catalytic complex.", image_url: "images/entries/7c2k.png", - query_url: "/ws/viewer/#/EMD-30275" + query_url: "/ws/viewer/#/7c2k+EMD-30275" }, { name: "6WXD", @@ -101,13 +101,13 @@ def self.selected_entries name: "6VSB + EMD-21375", description: "Spike: Decorating surface glycoprotein that protrudes from the viral outer membrane. Several conformational changes allow its interaction with the host receptor ACE2 and membrane fusion, thus initiating the infection.", image_url: "images/entries/6vsb.png", - query_url: "/ws/viewer/#/EMD-21375" + query_url: "/ws/viewer/#/6vsb+EMD-21375" }, { name: "6XDC + EMD-22136", description: "ORF3: As a viroporin, ORF3 forms cellular dimeric nonselective Ca2+ permeable cation channels that become active by oligomerizing into tetramers or higher-order oligomers. This channel activity in cells could be relevant to promote viral maturation through inhibition of autophagy and disruption of lysosomes.", image_url: "images/entries/6xcd.png", - query_url: "/ws/viewer/#/EMD-22136" + query_url: "/ws/viewer/#/6xdc+EMD-22136" }, { name: "7NTK", @@ -149,7 +149,7 @@ def self.selected_entries name: "7KDT + EMD-22829", description: "ORF9b: The gene encoding this small protein overlaps the N gene. ORF9b protein interacts and blocks the substrate binding site of the host Tom70, import receptor of the translocase from the mitochondrial outer membrane (TOM) complex, involved in the activation of the mitochondrial antiviral signaling leading to apoptosis upon viral infection. In addition, ORF9b may modulate interferon and apoptosis signaling avoiding the interaction between Tom70 and Hsp70 and Hsp90 chaperones.", image_url: "images/entries/7kdt.png", - query_url: "/ws/viewer/#/EMD-22829" + query_url: "/ws/viewer/#/7kdt+EMD-22829" }, ] end From 225c8fe4ddeb08c5562ff50f3b58df1a03790015 Mon Sep 17 00:00:00 2001 From: p3rcypj Date: Tue, 20 Feb 2024 17:28:08 +0000 Subject: [PATCH 7/7] Bump version --- README.md | 2 +- app/assets/javascripts/3dbio_viewer/package.json | 2 +- app/assets/javascripts/covid19/package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e4f61c37..0c3b33f0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 3DBIONOTES-WS v3.10.1 +# 3DBIONOTES-WS v3.10.2 ## Integrating molecular biology diff --git a/app/assets/javascripts/3dbio_viewer/package.json b/app/assets/javascripts/3dbio_viewer/package.json index 82fcc489..7200677c 100644 --- a/app/assets/javascripts/3dbio_viewer/package.json +++ b/app/assets/javascripts/3dbio_viewer/package.json @@ -1,6 +1,6 @@ { "name": "3dbio-viewer", - "version": "3.10.1", + "version": "3.10.2", "private": true, "dependencies": { "@3dbionotes/pdbe-molstar": "3.1.0-est-2", diff --git a/app/assets/javascripts/covid19/package.json b/app/assets/javascripts/covid19/package.json index 7bd5085a..becd54fc 100644 --- a/app/assets/javascripts/covid19/package.json +++ b/app/assets/javascripts/covid19/package.json @@ -1,7 +1,7 @@ { "name": "covid19", "description": "3dbionotes COVID-19", - "version": "3.10.1", + "version": "3.10.2", "homepage": ".", "dependencies": { "@dhis2/d2-i18n": "1.0.6", @@ -96,4 +96,4 @@ "typescript": "4.3.5", "wait-on": "5.2.1" } -} +} \ No newline at end of file