Skip to content

Commit

Permalink
Merge pull request #151 from luk27official/fix-saved-tasks
Browse files Browse the repository at this point in the history
Frontend updates
  • Loading branch information
luk27official authored Oct 23, 2024
2 parents d0a9ab1 + 58a5fdc commit a9fd7e3
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 27 deletions.
4 changes: 4 additions & 0 deletions frontend/client/custom-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
}
10 changes: 6 additions & 4 deletions frontend/client/tasks/server-docking-task.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

/**
Expand Down
3 changes: 0 additions & 3 deletions frontend/client/viewer/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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!);
Expand Down
16 changes: 10 additions & 6 deletions frontend/client/viewer/components/tasks-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -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: []
Expand Down Expand Up @@ -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({
Expand All @@ -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";
Expand Down
17 changes: 10 additions & 7 deletions frontend/client/viewer/components/tasks-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
};

Expand Down
7 changes: 3 additions & 4 deletions frontend/client/visualize/docking/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ export function DockingTask(dp: DockingTaskProps) {
}

return <div style={{ display: "flex" }}>
<div style={{ width: "50%", margin: "5px" }}>
<div style={{ width: "65%", margin: "5px" }}>
<DockingTaskVisualizationBox plugin={plugin!} changePocketsView={changePocketsView} pocket={prediction?.pockets.find((p: PocketData) => p.rank === pocketRank)}
changeBoundingBoxRefs={changeBoundingBoxRefs} polymerRepresentations={polymerRepresentations} />
</div>
<div id="content-wrapper" style={{ width: "50%", margin: "5px" }}>
<div id="content-wrapper" style={{ width: "35%", margin: "5px" }}>
<DockingTaskRightPanel pdbqtModels={pdbqtModels} dp={dp} plugin={plugin!} ligandRepresentations={ligandRepresentations} />
</div>
</div>;
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions frontend/client/visualize/docking/visualization-box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
<div id="molstar-wrapper" style={{ width: "100%", position: "relative", height: "75vh" }}></div>
<div id="molstar-wrapper" style={{ width: "100%", position: "relative", height: "74vh" }}></div>
<div id="visualization-tooltip">
<Tooltip title={<span style={{ fontSize: "1.5em", whiteSpace: "pre-wrap" }}>{tooltipText}</span>} placement="left-end">
<i className="bi bi-info-circle" style={{ "display": "block", zIndex: "1", position: "absolute", left: "47.5%", top: "77.5vh" }}></i>
<i className="bi bi-info-circle" style={{ "display": "block", zIndex: "1", position: "absolute", left: "62.5%", top: "76.5vh" }}></i>
</Tooltip>
</div>
<div className="visualization-toolbox-container" id="visualization-toolbox">
Expand Down

0 comments on commit a9fd7e3

Please sign in to comment.