Skip to content

Commit

Permalink
added functionality to remove custom flowsheet
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelPesce committed Nov 8, 2023
1 parent 365662f commit f5c717c
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 11 deletions.
74 changes: 68 additions & 6 deletions backend/app/internal/flowsheet_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import sys
import types
from xml.etree.ElementTree import QName
import os
import importlib

if sys.version_info < (3, 10):
from importlib_resources import files
Expand Down Expand Up @@ -74,6 +76,10 @@ def __init__(self, **kwargs):
self.app_settings = AppSettings(**kwargs)
self._objs, self._flowsheets = {}, {}

# Add custom flowsheets path to the system path
self.custom_flowsheets_path = Path.home() / ".watertap" / "custom_flowsheets"
sys.path.append(str(self.custom_flowsheets_path))

for package in self.app_settings.packages:
_log.debug(f"Collect flowsheet interfaces from package '{package}'")
for name, fsi in self._get_flowsheet_interfaces(package).items():
Expand Down Expand Up @@ -395,15 +401,71 @@ def _get_flowsheet_interfaces(

return interfaces

def add_custom_flowsheet(self, new_files, new_id):
"""Add new custom flowsheet to the mini db."""

query = tinydb.Query()
try:
custom_flowsheets_dict = self._histdb.search(query.fragment({"custom_flowsheets_version": VERSION}))
if(len(custom_flowsheets_dict) == 0):
_log.error('unable to find custom flowsheets dictionary')
custom_flowsheets_dict = {}
else:
custom_flowsheets_dict = custom_flowsheets_dict[0]["custom_flowsheets_dict"]
except Exception as e:
_log.error(f'error trying to find custom flowsheets dictionary: {e}')
_log.error(f'setting it as empty dictionary')
custom_flowsheets_dict = {}
custom_flowsheets_dict[new_id] = new_files

self._histdb.upsert(
{"custom_flowsheets_version": VERSION, "custom_flowsheets_dict": custom_flowsheets_dict},
(query.custom_flowsheets_version == VERSION),
)

self.add_custom_flowsheets()

def remove_custom_flowsheet(self, id_):
"""Remove a custom flowsheet from the mini db."""
query = tinydb.Query()
try:
custom_flowsheets_dict = self._histdb.search(query.fragment({"custom_flowsheets_version": VERSION}))
if(len(custom_flowsheets_dict) == 0):
_log.error('unable to find custom flowsheets dictionary')
custom_flowsheets_dict = {}
else:
custom_flowsheets_dict = custom_flowsheets_dict[0]["custom_flowsheets_dict"]
except Exception as e:
_log.error(f'error trying to find custom flowsheets dictionary: {e}')
_log.error(f'setting it as empty dictionary')
custom_flowsheets_dict = {}

# remove each file
flowsheet_files = custom_flowsheets_dict[id_]
for flowsheet_file in flowsheet_files:
flowsheet_file_path = self.custom_flowsheets_path / flowsheet_file
_log.info(f'flowsheet file path: {flowsheet_file_path}')
if os.path.isfile(flowsheet_file_path):
_log.info(f'removing file: {flowsheet_file_path}')
os.remove(flowsheet_file_path)


# delete from DB
del custom_flowsheets_dict[id_]
self._histdb.upsert(
{"custom_flowsheets_version": VERSION, "custom_flowsheets_dict": custom_flowsheets_dict},
(query.custom_flowsheets_version == VERSION),
)

# remove from flowsheets list
del self._flowsheets[id_]

self.add_custom_flowsheets()

def add_custom_flowsheets(self):
"""Search for user uploaded flowsheets. If found, add them as flowsheet interfaces."""
from os import walk
import importlib
custom_flowsheets_path = Path.home() / ".watertap" / "custom_flowsheets"
sys.path.append(str(custom_flowsheets_path))

files = []
for (_, _, filenames) in walk(custom_flowsheets_path):
for (_, _, filenames) in os.walk(self.custom_flowsheets_path):
files.extend(filenames)
break

Expand Down
17 changes: 15 additions & 2 deletions backend/app/routers/flowsheets.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,33 @@ async def upload_flowsheet(files: List[UploadFile]) -> str:
custom_flowsheets_path = Path.home() / ".watertap" / "custom_flowsheets"
try:
# get file contents

new_files = []

print('trying to read files with aiofiles')
for file in files:
# for file in files:
print(file.filename)
new_files.append(file.filename)
if '_ui.py' in file.filename:
new_id = file.filename.replace('.py', '')
async with aiofiles.open(f'{str(custom_flowsheets_path)}/{file.filename}', 'wb') as out_file:
content = await file.read() # async read
await out_file.write(content)
flowsheet_manager.add_custom_flowsheets()
flowsheet_manager.add_custom_flowsheet(new_files, new_id)
return {'return': 'success boy'}

except Exception as e:
_log.error(f"error on file upload: {str(e)}")
raise HTTPException(400, detail=f"File upload failed: {e}")

@router.post("/{flowsheet_id}/remove_flowsheet")
async def remove_flowsheet(flowsheet_id: str):
try:
flowsheet_manager.remove_custom_flowsheet(flowsheet_id)
return {'return': 'success boy'}
except Exception as e:
_log.error(f"error on flowsheet deletion: {str(e)}")
raise HTTPException(400, detail=f"failed: {e}")


@router.get("/{flowsheet_id}/load")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useState } from 'react'
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, IconButton, Icon, Button } from '@mui/material'
import { useNavigate } from "react-router-dom";
import { deleteFlowsheet } from "../../services/flowsheetsList.service";
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import ClearIcon from '@mui/icons-material/Clear';



export default function FlowsheetsListTable(props) {
Expand Down Expand Up @@ -56,6 +59,26 @@ export default function FlowsheetsListTable(props) {

}

const handleRemoveCustomFlowsheet = (e, id) => {
e.stopPropagation()
deleteFlowsheet(id)
.then(response => {
if (response.status === 200) {
response.json()
.then((data)=>{
console.log('delete successful: ',data)
window.location.reload()

}).catch((err)=>{
console.error("error on flowshete deletion: ",err)
})
}
else if (response.status === 400) {
console.error("error on flowshete deletion: ",response.statusText)
}
})
}

function compare( a, b ) {
if ( a[sortKey] < b[sortKey] ){
if(sortDirection === "ascending") return -1;
Expand Down Expand Up @@ -99,7 +122,13 @@ export default function FlowsheetsListTable(props) {
>
<TableCell>{row.description}</TableCell>
<TableCell align="right">{formatLastRun(row.last_run)}</TableCell>
<TableCell></TableCell>
<TableCell>
{row.custom &&
<IconButton size="small" onClick={(e) => handleRemoveCustomFlowsheet(e, row.id_)}>
<ClearIcon sx={{fontSize: "15px"}}/>
</IconButton>
}
</TableCell>
</TableRow>
))}
</TableBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function NewFlowsheetDialog(props) {
const [ showWarning, setShowWarning ] = useState(false)
const [ warningMessage, setWarningMessage ] = useState("")
const [ files, setFiles ] = useState({"Model File": null, "Export File": null, "Diagram File": null, "Data Files": []})
const fileTypes = {"Model File": ["py"], "Export File": ["py"], "Diagram File": ["png"], "Data Files": ["yaml", "yml", "json", "csv"], };
const fileTypes = {"Model File": ["py"], "Export File": ["py"], "Diagram File": ["png", "jpeg", "jpg"], "Data Files": ["yaml", "yml", "json", "csv", "txt", "zip"], };
const styles = {
modalStyle: {
position: 'absolute',
Expand Down Expand Up @@ -148,7 +148,7 @@ export default function NewFlowsheetDialog(props) {
try {
let newWarningMessage = "Please choose a valid file type from these options: "
for (let fileType of fileTypes[fileId]) {
newWarningMessage+= fileType+", "
newWarningMessage+= fileType+" "
}
setWarningMessage(newWarningMessage)
setShowWarning(true)
Expand Down
7 changes: 7 additions & 0 deletions electron/ui/src/services/flowsheetsList.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ export const uploadFlowsheet = (data) => {
mode: 'cors',
body: data
});
};

export const deleteFlowsheet = (id) => {
return fetch('http://localhost:8001/flowsheets/'+id+'/remove_flowsheet', {
method: 'POST',
mode: 'cors'
});
};

0 comments on commit f5c717c

Please sign in to comment.