diff --git a/js/package.json b/js/package.json
index d84b21d25..8f6775605 100644
--- a/js/package.json
+++ b/js/package.json
@@ -115,6 +115,7 @@
"geopattern": "^1.2.3",
"isomorphic-fetch": "^2.2.1",
"js-sha3": "^0.5.2",
+ "json2csv": "^3.7.1",
"lodash": "^4.11.1",
"marked": "^0.3.6",
"material-ui": "^0.16.1",
diff --git a/js/src/ui/Actionbar/Export/export.js b/js/src/ui/Actionbar/Export/export.js
index 64e153734..8e27b3451 100644
--- a/js/src/ui/Actionbar/Export/export.js
+++ b/js/src/ui/Actionbar/Export/export.js
@@ -15,7 +15,11 @@
// along with Parity. If not, see .
import React, { Component, PropTypes } from 'react';
+import IconMenu from 'material-ui/IconMenu';
+import MenuItem from 'material-ui/MenuItem';
+
import FileSaver from 'file-saver';
+import json2csv from 'json2csv';
import FileDownloadIcon from 'material-ui/svg-icons/file/file-download';
import { Button } from '../../';
@@ -30,27 +34,87 @@ class ActionbarExport extends Component {
className: PropTypes.string
}
+ state = {
+ menuOpen: false
+ }
+
render () {
const { className } = this.props;
return (
- }
- label='export'
- onClick={ this.onDownloadBackup } />
+ }
+ label='export'
+ onClick={ this.handleMenuOpen }
+ />
+ }
+ open={ this.state.menuOpen }
+ onRequestChange={ this.handleMenuChange }
+ onItemTouchTap={ this.handleExport }
+ targetOrigin={ { horizontal: 'right', vertical: 'top' } }
+ anchorOrigin={ { horizontal: 'right', vertical: 'top' } }
+ >
+
+
+
);
}
- onDownloadBackup = () => {
+ onDownloadBackup = (filetype) => {
const { filename, content } = this.props;
- const text = (typeof content === 'string')
- ? content
- : JSON.stringify(content, null, 4);
+ const text = this.contentAsString(content, filetype);
+ const extension = this.getExtension(filetype);
const blob = new Blob([ text ], { type: 'text/plain;charset=utf-8' });
- FileSaver.saveAs(blob, filename);
+ FileSaver.saveAs(blob, `${filename}.${extension}`);
+ }
+
+ getExtension = (filetype) => {
+ switch (filetype) {
+ case 'json':
+ case 'csv':
+ return filetype;
+ default:
+ return 'txt';
+ }
+ }
+
+ contentAsString = (data, filetype) => {
+ if (typeof data === 'string') {
+ return data;
+ }
+
+ switch (filetype) {
+ case 'json':
+ return JSON.stringify(data, null, 4);
+ case 'csv':
+ return this.toCSV(data);
+ default:
+ return data.toString();
+ }
+ }
+
+ toCSV = (data) => {
+ const json = Object.values(data);
+ console.log(json);
+ return json2csv({ data: json });
+ }
+
+ handleExport = (event, child) => {
+ const type = child.props.value;
+ this.onDownloadBackup(type);
+ }
+
+ handleMenuOpen = () => {
+ this.setState({ menuOpen: true });
+ }
+
+ handleMenuChange = (open) => {
+ this.setState({ menuOpen: open });
}
}
diff --git a/js/src/views/Accounts/accounts.js b/js/src/views/Accounts/accounts.js
index 821d493da..a256b7732 100644
--- a/js/src/views/Accounts/accounts.js
+++ b/js/src/views/Accounts/accounts.js
@@ -108,7 +108,7 @@ class Accounts extends Component {
,
+ filename='accounts' />,
this.renderSearchButton(),
this.renderSortButton()
diff --git a/js/src/views/Addresses/addresses.js b/js/src/views/Addresses/addresses.js
index 13c512713..3c5e8ad2f 100644
--- a/js/src/views/Addresses/addresses.js
+++ b/js/src/views/Addresses/addresses.js
@@ -105,7 +105,7 @@ class Addresses extends Component {
,
+ filename='addressbook' />,
this.renderSearchButton(),
this.renderSortButton()