diff --git a/frontend/client/custom-types.ts b/frontend/client/custom-types.ts index 96807ef..8c2cc69 100644 --- a/frontend/client/custom-types.ts +++ b/frontend/client/custom-types.ts @@ -291,4 +291,8 @@ export interface ServerTask { export interface ServerTaskLocalStorageData extends ServerTask { //potentially may contain more data discriminator: 'server'; // used to distinguish between ClientTask and ServerTask +} + +export function getLocalStorageKey(predictionInfo: PredictionInfo, key: string) { + return `${predictionInfo.id}_${predictionInfo.database}_${key}`; } \ No newline at end of file diff --git a/frontend/client/tasks/server-docking-task.tsx b/frontend/client/tasks/server-docking-task.tsx index d76b3fe..5a53d64 100644 --- a/frontend/client/tasks/server-docking-task.tsx +++ b/frontend/client/tasks/server-docking-task.tsx @@ -1,5 +1,5 @@ import { PredictionInfo, getApiEndpoint } from "../prankweb-api"; -import { PocketData, Point3D, ServerTaskInfo, ServerTaskLocalStorageData } from "../custom-types"; +import { getLocalStorageKey, PocketData, Point3D, ServerTaskInfo, ServerTaskLocalStorageData } from "../custom-types"; import { getPocketAtomCoordinates } from "../viewer/molstar-visualise"; import { PluginUIContext } from "molstar/lib/mol-plugin-ui/context"; @@ -148,9 +148,11 @@ export async function pollForDockingTask(predictionInfo: PredictionInfo) { return; }); //we could handle the error, but we do not care if the poll fails sometimes + const localStorageKey = getLocalStorageKey(predictionInfo, "serverTasks"); + if (taskStatusJSON) { //look into the local storage and check if there are any updates - let savedTasks = localStorage.getItem(`${predictionInfo.id}_serverTasks`); + let savedTasks = localStorage.getItem(localStorageKey); if (!savedTasks) savedTasks = "[]"; const tasks: ServerTaskLocalStorageData[] = JSON.parse(savedTasks); if (tasks.length === 0) return; @@ -179,12 +181,12 @@ export async function pollForDockingTask(predictionInfo: PredictionInfo) { } //save the updated tasks - localStorage.setItem(`${predictionInfo.id}_serverTasks`, JSON.stringify(tasks)); + localStorage.setItem(localStorageKey, JSON.stringify(tasks)); } } }); } - return localStorage.getItem(`${predictionInfo.id}_serverTasks`); + return localStorage.getItem(localStorageKey); } /** diff --git a/frontend/client/viewer/application.tsx b/frontend/client/viewer/application.tsx index c203537..ea2781d 100644 --- a/frontend/client/viewer/application.tsx +++ b/frontend/client/viewer/application.tsx @@ -58,9 +58,6 @@ export async function renderProteinView(predictionInfo: PredictionInfo) { visualizationToolbox.style.display = MolstarPlugin.layout.state.isExpanded ? "none" : "block"; }); - // Before rendering the data, clear the results of client-side tasks (currently removed). - // localStorage.removeItem(`${predictionInfo.id}_clientTasks`); - // Render pocket list on the right side (or bottom for smartphones) using React. const pocketListContainer = (window.innerWidth >= 768) ? document.getElementById('pocket-list-aside') : document.getElementById('pocket-list-aside-mobile'); const pocketListRoot = createRoot(pocketListContainer!); diff --git a/frontend/client/viewer/components/tasks-tab.tsx b/frontend/client/viewer/components/tasks-tab.tsx index a9f8aaf..cad91a0 100644 --- a/frontend/client/viewer/components/tasks-tab.tsx +++ b/frontend/client/viewer/components/tasks-tab.tsx @@ -4,7 +4,7 @@ import TextField from '@mui/material/TextField'; import MenuItem from '@mui/material/MenuItem'; import FormControl from '@mui/material/FormControl'; import Select, { SelectChangeEvent } from '@mui/material/Select'; -import { ClientTaskLocalStorageData, ClientTaskType, PocketData, ServerTaskLocalStorageData, ServerTaskType } from "../../custom-types"; +import { ClientTaskLocalStorageData, ClientTaskType, PocketData, ServerTaskLocalStorageData, ServerTaskType, getLocalStorageKey } from "../../custom-types"; import { Button, Paper, Typography } from "@mui/material"; import "./tasks-tab.css"; @@ -38,7 +38,9 @@ export default function TasksTab(props: { pockets: PocketData[], predictionInfo: type: TaskType.Client, name: "Volume", compute: (params, customName, pocketIndex) => { - let savedTasks = localStorage.getItem(`${props.predictionInfo.id}_clientTasks`); + const localStorageKey = getLocalStorageKey(props.predictionInfo, "clientTasks"); + + let savedTasks = localStorage.getItem(localStorageKey); if (savedTasks) { const tasks: ClientTaskLocalStorageData[] = JSON.parse(savedTasks); const task = tasks.find(task => task.pocket === (pocketIndex + 1) && task.type === ClientTaskType.Volume); @@ -50,7 +52,7 @@ export default function TasksTab(props: { pockets: PocketData[], predictionInfo: const promise = computePocketVolume(props.plugin, props.pockets[pocketIndex]); promise.then((volume: number) => { - savedTasks = localStorage.getItem(`${props.predictionInfo.id}_clientTasks`); + savedTasks = localStorage.getItem(localStorageKey); if (!savedTasks) savedTasks = "[]"; const tasks: ClientTaskLocalStorageData[] = JSON.parse(savedTasks); @@ -62,7 +64,7 @@ export default function TasksTab(props: { pockets: PocketData[], predictionInfo: "discriminator": "client", }); - localStorage.setItem(`${props.predictionInfo.id}_clientTasks`, JSON.stringify(tasks)); + localStorage.setItem(localStorageKey, JSON.stringify(tasks)); }); }, parameterDescriptions: [] @@ -106,7 +108,9 @@ export default function TasksTab(props: { pockets: PocketData[], predictionInfo: handleInvalidDockingInput(""); - let savedTasks = localStorage.getItem(`${props.predictionInfo.id}_serverTasks`); + const localStorageKey = getLocalStorageKey(props.predictionInfo, "serverTasks"); + + let savedTasks = localStorage.getItem(localStorageKey); if (!savedTasks) savedTasks = "[]"; const tasks: ServerTaskLocalStorageData[] = JSON.parse(savedTasks); tasks.push({ @@ -119,7 +123,7 @@ export default function TasksTab(props: { pockets: PocketData[], predictionInfo: "responseData": null, "discriminator": "server", }); - localStorage.setItem(`${props.predictionInfo.id}_serverTasks`, JSON.stringify(tasks)); + localStorage.setItem(localStorageKey, JSON.stringify(tasks)); const taskPostRequest = computeDockingTaskOnBackend(props.predictionInfo, props.pockets[pocketIndex], smiles, props.plugin, exhaustiveness); if (taskPostRequest === null) { tasks[tasks.length - 1].status = "failed"; diff --git a/frontend/client/viewer/components/tasks-table.tsx b/frontend/client/viewer/components/tasks-table.tsx index 67a275e..1bfda41 100644 --- a/frontend/client/viewer/components/tasks-table.tsx +++ b/frontend/client/viewer/components/tasks-table.tsx @@ -12,7 +12,7 @@ import { useInterval } from "./tools"; import "bootstrap-icons/font/bootstrap-icons.css"; import { PocketData, ServerTaskTypeVisualizationDescriptors } from "../../custom-types"; -import { ClientTaskLocalStorageData, ServerTaskLocalStorageData, ServerTaskTypeDescriptors, ClientTaskTypeDescriptors, ClientTaskType, ServerTaskType } from "../../custom-types"; +import { ClientTaskLocalStorageData, ServerTaskLocalStorageData, ServerTaskTypeDescriptors, ClientTaskTypeDescriptors, ClientTaskType, ServerTaskType, getLocalStorageKey } from "../../custom-types"; import { dockingHash, downloadDockingResult, pollForDockingTask } from "../../tasks/server-docking-task"; import { Order, getComparator, isInstanceOfClientTaskLocalStorageData, isInstanceOfServerTaskLocalStorageData } from "./tools"; import { PredictionInfo } from "../../prankweb-api"; @@ -104,12 +104,15 @@ function EnhancedTableHead(props: EnhancedTableProps) { export function TasksTable(props: { pocket: PocketData | null, predictionInfo: PredictionInfo; }) { - let serverTasks = localStorage.getItem(`${props.predictionInfo.id}_serverTasks`); + const localStorageServerKey = getLocalStorageKey(props.predictionInfo, "serverTasks"); + const localStorageClientKey = getLocalStorageKey(props.predictionInfo, "clientTasks"); + + let serverTasks = localStorage.getItem(localStorageServerKey); if (!serverTasks) serverTasks = "[]"; let serverTasksParsed: ServerTaskLocalStorageData[] = JSON.parse(serverTasks); if (props.pocket !== null) serverTasksParsed = serverTasksParsed.filter((task: ServerTaskLocalStorageData) => task.pocket === Number(props.pocket!.rank)); - let clientTasks = localStorage.getItem(`${props.predictionInfo.id}_clientTasks`); + let clientTasks = localStorage.getItem(localStorageClientKey); if (!clientTasks) clientTasks = "[]"; let clientTasksParsed: ClientTaskLocalStorageData[] = JSON.parse(clientTasks); if (props.pocket !== null) clientTasksParsed = clientTasksParsed.filter((task: ClientTaskLocalStorageData) => task.pocket === Number(props.pocket!.rank)); @@ -171,16 +174,16 @@ export function TasksTable(props: { pocket: PocketData | null, predictionInfo: P useInterval(pollDocking, 1000 * 7); const removeClientTaskFromLocalStorage = (task: ClientTaskLocalStorageData) => () => { - const clientTasksParsed: ClientTaskLocalStorageData[] = JSON.parse(localStorage.getItem(`${props.predictionInfo.id}_clientTasks`) || "[]"); + const clientTasksParsed: ClientTaskLocalStorageData[] = JSON.parse(localStorage.getItem(localStorageClientKey) || "[]"); const newClientTasks = clientTasksParsed.filter((t: ClientTaskLocalStorageData) => t.created !== task.created); - localStorage.setItem(`${props.predictionInfo.id}_clientTasks`, JSON.stringify(newClientTasks)); + localStorage.setItem(localStorageClientKey, JSON.stringify(newClientTasks)); setRender(numRenders + 1); }; const removeServerTaskFromLocalStorage = (task: ServerTaskLocalStorageData) => () => { - const serverTasksParsed: ServerTaskLocalStorageData[] = JSON.parse(localStorage.getItem(`${props.predictionInfo.id}_serverTasks`) || "[]"); + const serverTasksParsed: ServerTaskLocalStorageData[] = JSON.parse(localStorage.getItem(localStorageServerKey) || "[]"); const newServerTasks = serverTasksParsed.filter((t: ServerTaskLocalStorageData) => t.created !== task.created); - localStorage.setItem(`${props.predictionInfo.id}_serverTasks`, JSON.stringify(newServerTasks)); + localStorage.setItem(localStorageServerKey, JSON.stringify(newServerTasks)); setRender(numRenders + 1); }; diff --git a/frontend/client/visualize/docking/main.tsx b/frontend/client/visualize/docking/main.tsx index 774d3e0..c5079ac 100644 --- a/frontend/client/visualize/docking/main.tsx +++ b/frontend/client/visualize/docking/main.tsx @@ -146,11 +146,11 @@ export function DockingTask(dp: DockingTaskProps) { } return
-
+
p.rank === pocketRank)} changeBoundingBoxRefs={changeBoundingBoxRefs} polymerRepresentations={polymerRepresentations} />
-
+
; @@ -170,8 +170,7 @@ async function loadLigandIntoMolstar(plugin: PluginUIContext | undefined, docked const structure = await plugin.builders.structure.createStructure(mdl, { name: 'model', params: {} }); const representation = await plugin.builders.structure.representation.addRepresentation(structure, { type: 'ball-and-stick', - color: 'uniform', - colorParams: { value: Color(0xff00ff) }, + color: 'element-symbol' }); // hide the ligands, keep just the first model visible diff --git a/frontend/client/visualize/docking/visualization-box.tsx b/frontend/client/visualize/docking/visualization-box.tsx index e93ef6e..47331fd 100644 --- a/frontend/client/visualize/docking/visualization-box.tsx +++ b/frontend/client/visualize/docking/visualization-box.tsx @@ -44,14 +44,14 @@ export function DockingTaskVisualizationBox({ plugin, changePocketsView, pocket, plugin.canvas3d?.requestCameraReset(); }; - const tooltipText = `Ligands shown in blue color are a part of the loaded structure.\nLigands shown in violet color are the docked ligands.\n\nNote that the bounding box does not represent the actual bounding box size and is shown for reference only.`; + const tooltipText = `Ligands shown in blue color are a part of the loaded structure.\nLigands colored by element symbols are the docked ligands.\n\nNote that the bounding box does not represent the actual bounding box size and is shown for reference only.`; return ( <> -
+
{tooltipText}} placement="left-end"> - +