Skip to content

Commit

Permalink
Merge pull request #288 from RobokopU24/feature/csv-export
Browse files Browse the repository at this point in the history
Feature/csv export
  • Loading branch information
Woozl authored Dec 10, 2024
2 parents b8e663d + af27eb7 commit 73cab88
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 63 deletions.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"body-parser": "^1.20.0",
"bootstrap": "^3.4.1",
"core-js": "^3.6.5",
"csv-stringify": "^6.5.2",
"d3": "^6.5.0",
"d3-force": "^2.1.1",
"dotenv": "^8.6.0",
Expand Down
95 changes: 95 additions & 0 deletions src/components/DownloadDialog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import Radio from '@material-ui/core/Radio';
import RadioGroup from '@material-ui/core/RadioGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import csv from 'csv-stringify';

const jsonToCsvString = (json) => new Promise((res, rej) => {
csv.stringify(json, (err, output) => {
if (err) rej(err);
else res(output);
});
});

export default function DownloadDialog({
open, setOpen, message,
}) {
const [type, setType] = React.useState('json');
const [fileName, setFileName] = React.useState('ROBOKOP_message');

const handleClose = () => {
setOpen(false);
};

const handleClickDownload = async () => {
let blob;
if (type === 'json') {
blob = new Blob([JSON.stringify({ message }, null, 2)], { type: 'application/json' });
}
if (type === 'csv') {
const subsetMessage = message.results.map((r) => [...Object.values(r.node_bindings).map((nb) => nb[0].id), r.score]);
const csvString = await jsonToCsvString(subsetMessage);
blob = new Blob([csvString], { type: 'text/csv' });
}

const a = document.createElement('a');
a.download = `${fileName}.${type}`;
a.href = window.URL.createObjectURL(blob);
document.body.appendChild(a);
a.click();
a.remove();

handleClose();
};

return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
>
<DialogTitle id="alert-dialog-title">Download Answer</DialogTitle>
<DialogContent style={{ width: 600 }}>
<TextField
label="File name"
fullWidth
variant="outlined"
style={{ marginBottom: '2rem' }}
value={fileName}
onChange={(e) => { setFileName(e.target.value); }}
/>

<FormControl component="fieldset">
<RadioGroup aria-label="gender" name="gender1" value={type} onChange={(e) => { setType(e.target.value); }}>
<FormControlLabel value="json" control={<Radio />} label="JSON" />
<FormControlLabel value="csv" control={<Radio />} label="CSV" />
</RadioGroup>
</FormControl>

{
type === 'csv' && (
<DialogContentText style={{ fontSize: '1em' }}>
The CSV download contains a smaller subset of the answer information. To analyze the complete properties of the answer graphs, consider using JSON.
</DialogContentText>
)
}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClickDownload} color="primary" variant="contained">
Download
</Button>
</DialogActions>
</Dialog>
);
}
68 changes: 9 additions & 59 deletions src/pages/answer/leftDrawer/LeftDrawer.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState } from 'react';
import { useRouteMatch } from 'react-router-dom';
import Drawer from '@material-ui/core/Drawer';
import Toolbar from '@material-ui/core/Toolbar';
import List from '@material-ui/core/List';
Expand All @@ -9,14 +8,11 @@ import ListItemText from '@material-ui/core/ListItemText';
import Checkbox from '@material-ui/core/Checkbox';
import IconButton from '@material-ui/core/IconButton';

import { useAuth0 } from '@auth0/auth0-react';

import CloudUploadIcon from '@material-ui/icons/CloudUpload';
import PublishIcon from '@material-ui/icons/Publish';
import GetAppIcon from '@material-ui/icons/GetApp';
import HighlightOffIcon from '@material-ui/icons/HighlightOff';

import ConfirmDialog from '~/components/ConfirmDialog';
import DownloadDialog from '~/components/DownloadDialog';

import './leftDrawer.css';

Expand All @@ -31,30 +27,15 @@ import './leftDrawer.css';
* @param {boolean} owned - does the user own this answer
*/
export default function LeftDrawer({
onUpload, displayState, updateDisplayState, message,
saveAnswer, deleteAnswer, owned,
onUpload, displayState, updateDisplayState, message, deleteAnswer,
}) {
const { isAuthenticated } = useAuth0();
const urlHasAnswerId = useRouteMatch('/answer/:answer_id');
const [confirmOpen, setConfirmOpen] = useState(false);
const [downloadOpen, setDownloadOpen] = useState(false);

function toggleDisplay(component, show) {
updateDisplayState({ type: 'toggle', payload: { component, show } });
}

/**
* Download the current message
*/
async function download() {
const blob = new Blob([JSON.stringify({ message }, null, 2)], { type: 'application/json' });
const a = document.createElement('a');
a.download = 'ROBOKOP_message.json';
a.href = window.URL.createObjectURL(blob);
document.body.appendChild(a);
a.click();
a.remove();
}

return (
<Drawer
container={document.getElementById('contentContainer')}
Expand Down Expand Up @@ -86,7 +67,7 @@ export default function LeftDrawer({
component="label"
button
disabled={!Object.keys(message).length}
onClick={download}
onClick={() => { setDownloadOpen(true); }}
>
<ListItemIcon>
<IconButton
Expand Down Expand Up @@ -123,42 +104,6 @@ export default function LeftDrawer({
onChange={(e) => onUpload(e)}
/>
</ListItem>
<ListItem
component="label"
button
disabled={!Object.keys(message).length || !!urlHasAnswerId || !isAuthenticated}
onClick={saveAnswer}
>
<ListItemIcon>
<IconButton
component="span"
style={{ fontSize: '18px' }}
title="Save Answer"
disableRipple
>
<CloudUploadIcon />
</IconButton>
</ListItemIcon>
<ListItemText primary="Save To Library" />
</ListItem>
<ListItem
component="label"
button
disabled={!urlHasAnswerId || !isAuthenticated || !owned}
onClick={() => setConfirmOpen(true)}
>
<ListItemIcon>
<IconButton
component="span"
style={{ fontSize: '18px' }}
title="Delete Answer"
disableRipple
>
<HighlightOffIcon />
</IconButton>
</ListItemIcon>
<ListItemText primary="Delete Answer" />
</ListItem>
</List>
<ConfirmDialog
open={confirmOpen}
Expand All @@ -171,6 +116,11 @@ export default function LeftDrawer({
title="Confirm Answer Deletion"
confirmText="Delete Answer"
/>
<DownloadDialog
open={downloadOpen}
setOpen={setDownloadOpen}
message={message}
/>
</Drawer>
);
}
8 changes: 4 additions & 4 deletions src/pages/explore/DrugDiseasePairs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export default function DrugDiseasePairs() {
query_graph: {
nodes: {
n0: {
name: pair.disease.name,
ids: [pair.disease.id],
name: pair.disease_name,
ids: [pair.disease_id],
},
n1: {
name: pair.drug.name,
ids: [pair.drug.id],
name: pair.drug_name,
ids: [pair.drug_id],
},
},
edges: {
Expand Down

0 comments on commit 73cab88

Please sign in to comment.