Skip to content

Commit

Permalink
668 lab 627 fix add tool issues (#676)
Browse files Browse the repository at this point in the history
Co-authored-by: Aakaash Meduri <aakaash.meduri@gmail.com>
  • Loading branch information
thetechnocrat-dev and acashmoney committed Sep 28, 2023
1 parent 16d0986 commit c35e3f0
Show file tree
Hide file tree
Showing 22 changed files with 1,409 additions and 385 deletions.
2 changes: 1 addition & 1 deletion frontend/app/datafile/add/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function DataFileForm() {
dispatch(setError("Please select a file"))
return
}

dispatch(startLoading())
dispatch(setError(null))
const metadata = { walletAddress };
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function RootLayout(props: React.PropsWithChildren) {
<Box display="flex" flexDirection="column" height="100vh"> {/* Fill entire view height and set up for flex */}
<TopNav />

<Container maxWidth="lg">
<Container maxWidth="lg" style={{paddingBottom: "40px"}}>
<Box mt={5} mb={5} flexGrow={1} display="flex" alignItems="center" justifyContent="center"> {/* Center content */}
<Grid container direction="column" spacing={3}>
<Grid item xs={12}>
Expand Down
311 changes: 70 additions & 241 deletions frontend/app/tool/add/page.tsx
Original file line number Diff line number Diff line change
@@ -1,268 +1,97 @@
'use client'

import React, { useState } from 'react'
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { addToolAsync, selectWalletAddress, setError, startFileUpload, endFileUpload } from '@/lib/redux'
import { useRouter } from 'next/navigation'
import {
selectToolError,
selectToolIsLoading,
selectToolIsUploaded
} from '@/lib/redux/slices/toolAddSlice/selectors'
import TextField from '@mui/material/TextField'
AppDispatch,
setAddToolError,
setAddToolLoading,
setAddToolJson,
setAddToolSuccess,
selectWalletAddress,
selectAddToolLoading,
selectAddToolError,
selectAddToolJson,
selectAddToolSuccess,
createToolThunk,
} from '@/lib/redux'
import Button from '@mui/material/Button'
import Box from '@mui/material/Box'
import Grid from '@mui/material/Grid'
// import { useRouter } from 'next/router'
import Alert from '@mui/material/Alert'
import Typography from '@mui/material/Typography'
import { JsonInput } from '@mantine/core'
import { MantineProvider } from '@mantine/core';


export default function AddTool() {
const dispatch = useDispatch()
// const router = useRouter()
const dispatch = useDispatch<AppDispatch>()
const router = useRouter()

const isLoading = useSelector(selectToolIsLoading);
const error = useSelector(selectToolError);
const isUploaded = useSelector(selectToolIsUploaded);
const walletAddress = useSelector(selectWalletAddress)

const sampleToolConfig = {
"class": "CommandLineTool",
"name": "equibind",
"description": "Docking of small molecules to a protein",
"author": "@misc{stärk2022equibind,\n title={EquiBind: Geometric Deep Learning for Drug Binding Structure Prediction}, \n author={Hannes Stärk and Octavian-Eugen Ganea and Lagnajit Pattanaik and Regina Barzilay and Tommi Jaakkola},\n year={2022},\n eprint={2202.05146},\n archivePrefix={arXiv},\n primaryClass={q-bio.BM}\n}",
"baseCommand": ["/bin/bash", "-c"],
"arguments": [
"mkdir -p /tmp-inputs/tmp;",
"mkdir -p /tmp-outputs/tmp;",
"cp /inputs/* /tmp-inputs/tmp/;",
"ls /tmp-inputs/tmp;",
"cd /src && python /src/inference.py --config=/src/configs_clean/bacalhau.yml;",
"mv /tmp-outputs/tmp/* /outputs/;",
"mv /outputs/lig_equibind_corrected.sdf /outputs/$(inputs.protein.basename)_$(inputs.small_molecule.basename)_docked.$(inputs.small_molecule.ext);",
"mv /tmp-inputs/tmp/*.pdb /outputs/;"],
"dockerPull": "ghcr.io/labdao/equibind:main@sha256:21a381d9ab1ff047565685044569c8536a55e489c9531326498b28d6b3cc244f",
"gpuBool": false,
"networkBool": false,
"inputs": {
"protein": {
"type": "File",
"item": "",
"glob": ["*.pdb"]
},
"small_molecule": {
"type": "File",
"item": "",
"glob": ["*.sdf", "*.mol2"]
}
},
"outputs": {
"best_docked_small_molecule": {
"type": "File",
"item": "",
"glob": ["*_docked.sdf", "*_docked.mol2"]
},
"protein": {
"type": "File",
"item": "",
"glob": ["*.pdb"]
}
const loading = useSelector(selectAddToolLoading)
const error = useSelector(selectAddToolError)
const toolJson = useSelector(selectAddToolJson)
const toolSuccess = useSelector(selectAddToolSuccess)

useEffect(() => {
if (toolSuccess) {
setAddToolSuccess(false)
dispatch(setAddToolJson(""))
router.push('/tool/list')
}
}

const [toolClass, setToolClass] = useState(sampleToolConfig.class)
const [name, setName] = useState(sampleToolConfig.name);
const [description, setDescription] = useState(sampleToolConfig.description);
const [author, setAuthor] = useState(sampleToolConfig.author);
const [baseCommand, setBaseCommand] = useState(sampleToolConfig.baseCommand);
const [toolArguments, setToolArguments] = useState(sampleToolConfig.arguments);
const [dockerPull, setDockerPull] = useState(sampleToolConfig.dockerPull);
const [gpuBool, setGpuBool] = useState(sampleToolConfig.gpuBool);
const [networkBool, setNetworkBool] = useState(sampleToolConfig.networkBool);
const [inputs, setInputs] = useState(sampleToolConfig.inputs);
const [outputs, setOutputs] = useState(sampleToolConfig.outputs);

const handleToolClassChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setToolClass(e.target.value);
};

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};

const handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setDescription(e.target.value);
};

const handleAuthorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setAuthor(e.target.value);
};

const handleBaseCommandChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setBaseCommand(e.target.value.split(','));
};

const handleToolArgumentsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setToolArguments(e.target.value.split(','));
};
}, [toolSuccess, dispatch])

const handleDockerPullChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setDockerPull(e.target.value);
};

const handleGpuBoolChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setGpuBool(e.target.checked);
};

const handleNetworkBoolChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNetworkBool(e.target.checked);
};

const handleInputsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
try {
const value = JSON.parse(e.target.value);
setInputs(value);
} catch (error) {
console.error(error);
}
};
const handleToolJsonChange = (toolJsonInput: string) => {
dispatch(setAddToolJson(toolJsonInput))
}

const handleOutputsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log("Submitting tool.json: ", toolJson);
dispatch(setAddToolLoading(true))
dispatch(setAddToolError(""))
try {
const value = JSON.parse(e.target.value);
setOutputs(value);
const toolJsonParsed = JSON.parse(toolJson)
await dispatch(createToolThunk({ walletAddress, toolJson: toolJsonParsed }))
} catch (error) {
console.error(error);
console.error("Error creating tool", error)
dispatch(setAddToolError("Error creating tool"))
}
};

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();

console.log("Submitting tool config")
console.log("Wallet address: ", walletAddress)

const toolConfig = {
"name": name,
"description": description,
"author": author,
"baseCommand": baseCommand,
"arguments": toolArguments,
"dockerPull": dockerPull,
"gpuBool": gpuBool,
"networkBool": networkBool,
"inputs": inputs,
"outputs": outputs
};

// @ts-ignore
dispatch(addToolAsync({ toolData: toolConfig, walletAddress }));
// router.push('/tool/list');
};
dispatch(setAddToolLoading(false))
}

return (
<form onSubmit={handleSubmit}>
<Box maxWidth={500} margin="auto">
<Grid container direction="column" spacing={2}>
<Grid item>
<TextField
fullWidth
label="Tool Class"
variant="outlined"
value={toolClass}
onChange={handleToolClassChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Tool Name"
variant="outlined"
value={name}
onChange={handleNameChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Description"
variant="outlined"
value={description}
onChange={handleDescriptionChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Author"
variant="outlined"
value={author}
onChange={handleAuthorChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Base Command"
variant="outlined"
value={baseCommand}
onChange={handleBaseCommandChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Arguments"
variant="outlined"
value={toolArguments}
onChange={handleToolArgumentsChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Docker Pull"
variant="outlined"
value={dockerPull}
onChange={handleDockerPullChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="GPU Bool"
variant="outlined"
value={gpuBool}
onChange={handleGpuBoolChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Network Bool"
variant="outlined"
value={networkBool}
onChange={handleNetworkBoolChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Inputs"
variant="outlined"
value={inputs}
onChange={handleInputsChange}
/>
</Grid>
<Grid item>
<TextField
fullWidth
label="Outputs"
variant="outlined"
value={outputs}
onChange={handleOutputsChange}
/>
<Grid container direction="column" spacing={2} justifyContent="center" alignItems="center">
<Grid style={{ width: '100%' }} item>
<MantineProvider>
<JsonInput
label="Tool Definition"
placeholder="Paste your tool's JSON definition here."
validationError="Invalid JSON"
autosize
minRows={10}
value={toolJson}
onChange={handleToolJsonChange}
styles={{
input: { 'width': '100%' },
}}
/>
</MantineProvider>
</Grid>
{error && (
<Box my={2}>
<Alert severity="error" variant="filled">
<Typography align="center">{error}</Typography>
</Alert>
</Box>
)}
<Grid item container justifyContent="center">
<Button variant="contained" color="primary" type="submit">
{isLoading ? "Submitting..." : "Submit"}
{loading ? "Submitting..." : "Submit"}
</Button>
</Grid>
</Grid>
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/tool/list/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import backendUrl from 'lib/backendUrl'
export default function ListToolFiles() {
interface Tool {
CID: string;
ToolJSON: string;
Name: string;
WalletAddress: string;
}

Expand Down Expand Up @@ -41,20 +41,20 @@ export default function ListToolFiles() {
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>CID</TableCell>
<TableCell>Serialized Tool Config</TableCell>
<TableCell>Uploader Wallet Address</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tools.map((tool, index) => (
<TableRow key={index}>
<TableCell>{tool.Name}</TableCell>
<TableCell>
<a href={`http://bacalhau.labdao.xyz:8080/ipfs/${tool.CID}/`}>
{tool.CID}
</a>
</TableCell>
<TableCell>{JSON.stringify(tool.ToolJSON)}</TableCell>
<TableCell>{tool.WalletAddress}</TableCell>
</TableRow>
))}
Expand Down

0 comments on commit c35e3f0

Please sign in to comment.