Skip to content

Commit

Permalink
Merge branch 'development' into feature/nmr
Browse files Browse the repository at this point in the history
  • Loading branch information
p3rcypj committed Feb 22, 2024
2 parents 3432257 + 4127457 commit 83627d1
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 3DBIONOTES-WS v3.10.0
# 3DBIONOTES-WS v3.10.2

## Integrating molecular biology

Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/3dbio_viewer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "3dbio-viewer",
"version": "3.10.0",
"version": "3.10.2",
"private": true,
"dependencies": {
"@3dbionotes/pdbe-molstar": "3.1.0-est-2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}`),
Expand Down Expand Up @@ -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([]);
Expand Down Expand Up @@ -241,8 +244,8 @@ export function usePdbePlugin(options: MolecularStructureProps) {
loaderKeys.uploadedModel,
new Promise<void>((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);
Expand Down Expand Up @@ -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,
Expand All @@ -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),
});
});
}
Expand Down Expand Up @@ -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,
Expand All @@ -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),
});
});
}
Expand All @@ -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)),
Expand All @@ -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),
});
});
}
Expand Down Expand Up @@ -545,29 +548,61 @@ function getId<T extends { id: string }>(obj: T): string {
return obj.id;
}

export async function checkModelUrl(id: Maybe<string>, modelType: Type): Promise<boolean> {
if (!id) return false;
export async function checkModelUrl(id: Maybe<string>, modelType: Type): Promise<Response> {
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<boolean> {
export async function checkUploadedModelUrl(url: string): Promise<Response> {
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 };
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
applySelectionChangesToPlugin,
checkModelUrl,
checkUploadedModelUrl,
getErrorByStatus,
getLigandView,
loaderErrors,
} from "./usePdbPlugin";
Expand Down Expand Up @@ -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));
}
Expand Down
24 changes: 24 additions & 0 deletions app/assets/javascripts/3dbio_viewer/src/webapp/pages/app/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,27 @@ 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;
}

.rangeForm .inputs input {
width: 70px;
}
4 changes: 2 additions & 2 deletions app/assets/javascripts/covid19/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "covid19",
"description": "3dbionotes COVID-19",
"version": "3.10.0",
"version": "3.10.2",
"homepage": ".",
"dependencies": {
"@dhis2/d2-i18n": "1.0.6",
Expand Down Expand Up @@ -96,4 +96,4 @@
"typescript": "4.3.5",
"wait-on": "5.2.1"
}
}
}
10 changes: 5 additions & 5 deletions app/models/covid19.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 83627d1

Please sign in to comment.