Skip to content

Commit

Permalink
Merge pull request #1612 from hackforla/sb/exportbutton
Browse files Browse the repository at this point in the history
Sb/exportbutton
  • Loading branch information
sophia-bui authored Jan 11, 2024
2 parents 2250b72 + 9149a9a commit a829d91
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 14 deletions.
95 changes: 95 additions & 0 deletions components/main/Desktop/ExportButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useContext } from 'react';
import Button from '@mui/material/Button';
import PropTypes from 'proptypes';
import { connect } from 'react-redux';
import JSZip from 'jszip';
import Papa from 'papaparse';
import { saveAs } from 'file-saver';
import DbContext from '@db/DbContext';
import ddbh from '@utils/duckDbHelpers.js';
import { isEmpty } from '@utils';
import requestTypes from '../../../data/requestTypes';

// export button main function
function ExportButton({ filters }) {
const { conn } = useContext(DbContext);

// creation zip file
const downloadZip = async csvContent => {
const zip = new JSZip();
zip.file('NeighborhoodData.csv', csvContent);

const content = await zip.generateAsync({ type: 'blob' });
saveAs(content, '311Data.zip');
};

// data to add into zip file, queries then add results
const getDataToExport = async () => {
// define request status filter variable to reuse variable
let requestStatusFilter = '';

if (filters.requestStatus.open === true && filters.requestStatus.closed === false) {
// Only open is true, get all open requests
// query = `SELECT * FROM requests WHERE Status='Open';`;
requestStatusFilter = 'Open';
} else if (filters.requestStatus.closed === true && filters.requestStatus.open === false) {
// Only closed is true, get all closed requests
// query = `SELECT * FROM requests WHERE Status='Closed';`;
requestStatusFilter = 'Closed';
}

const formattedRequestTypes = requestTypes
.filter(item => filters.requestTypes[item.typeId])
.map(v => `'${v.typeName}'`)
.join(', ');

// // in the case user chooses one neighborhood or all are selected + dates and status
const query = `select * from requests where CreatedDate >= '${filters.startDate}' AND
CreatedDate < '${filters.endDate}'${requestStatusFilter !== ''
? ` AND Status='${requestStatusFilter}'` : ''}
${filters.councilId !== null
? ` AND NC='${filters.councilId}'` : ''} AND RequestType IN (${formattedRequestTypes});`;

const dataToExport = await conn.query(query);
const results = ddbh.getTableData(dataToExport);

if (!isEmpty(results)) {
// results chosen to csv
const csvContent = Papa.unparse(results);
downloadZip(csvContent);
} else {
window.alert('No 311 data available within the selected filters. Please adjust your filters and try again.');
}
};

// action upon clicking
const handleExport = () => {
getDataToExport(filters);
};

return (
<Button variant="contained" onClick={handleExport}>
Export
</Button>

);
}

const mapStateToProps = state => ({
filters: state.filters,
});

export default connect(mapStateToProps)(ExportButton);

ExportButton.propTypes = {
filters: PropTypes.shape({
startDate: PropTypes.string,
endDate: PropTypes.string,
councilId: PropTypes.number,
requestStatus: PropTypes.shape({
open: PropTypes.bool,
closed: PropTypes.bool,
}),
requestTypes: PropTypes.objectOf(PropTypes.bool),
}).isRequired,
};
4 changes: 4 additions & 0 deletions components/main/Desktop/FilterMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import TypeSelector from '@components/main/Desktop/TypeSelector';
import StatusSelector from '@components/main/Desktop/StatusSelector';
import CouncilSelector from '@components/main/Desktop/CouncilSelector';
import ShareableLinkCreator from '@components/main/Desktop/ShareableLinkCreator';
// import ExportButton from '@components/main/Desktop/ExportButton';

// import GearButton from '@components/common/GearButton';
// import clsx from 'clsx';
Expand Down Expand Up @@ -123,6 +124,9 @@ function FilterMenu({ resetMap, resetAddressSearch }) {
<div className={classes.selectorWrapper}>
<ShareableLinkCreator />
</div>
{/* <div className={classes.selectorWrapper}>
<ExportButton />
</div> */}
</CardContent>
</Collapse>
</Card>
Expand Down
67 changes: 53 additions & 14 deletions package-lock.json

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

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@
"dataframe-js": "^1.4.4",
"dotenv": "^16.3.1",
"dotenv-webpack": "^8.0.1",
"file-saver": "^2.0.5",
"html-webpack-plugin": "^5.5.3",
"jszip": "^3.10.1",
"lodash.debounce": "^4.0.8",
"mapbox-gl": "^2.15.0",
"mixpanel-browser": "^2.47.0",
"moment": "^2.29.4",
"papaparse": "^5.4.1",
"prop-types": "^15.8.1",
"proptypes": "^1.1.0",
"query-string": "^8.1.0",
Expand Down

0 comments on commit a829d91

Please sign in to comment.