// @flow import React from 'react'; import { Modal, Form, Radio, Select, Button } from 'antd'; import get from 'lodash/get'; import { withApollo } from 'react-apollo'; import {FormattedMessage, injectIntl} from 'react-intl'; import gql from 'graphql-tag'; const FormItem = Form.Item; const RadioGroup = Radio.Group; const Option = Select.Option; type Props = { form: Object, value: Array, selectedValue: Array, fileName: string, triggerModal: Function, fields: Array, client: any, intl: Object, title: string, visible: boolean, query: Object, keyName: string } type State = { downloading: boolean } const ALL = 'ALL'; const THIS_PAGE = 'THIS_PAGE'; const SELECTED = 'SElECTED'; const DOWNLOAD = 'DOWNLOAD'; // $FlowFixMe @injectIntl @withApollo @Form.create() export default class ExportModal extends React.Component { state = { downloading: false }; handleSubmit = (e: Event) => { e.preventDefault(); const { form, value, selectedValue, fileName, triggerModal, fields, client, query, keyName } = this.props; form.validateFields((err, values) => { if (!err) { const {exportData, exportFieldKeys, exportWay} = values; let getData = Promise.resolve([]); if (exportData === ALL) { // have to fetch data without pagination data const queries = query.getQueries([keyName]).args; const variables = query.getVairables(); delete variables[queries.first.substr(1)]; delete variables[queries.after.substr(1)]; delete variables[queries.last.substr(1)]; delete variables[queries.before.substr(1)]; getData = client.query({ query: gql`${query.toGQL(keyName)}`, // remove pagination field variables }).then(result => { return result.data[keyName].edges.map(edge => edge.node); }) } else if (exportData === THIS_PAGE) { getData = Promise.resolve(value); } else if (exportData === SELECTED) { getData = Promise.resolve(selectedValue); } const fieldsData = fields.filter(field => exportFieldKeys.find(key => key === field.keyName)); if (exportWay === DOWNLOAD) { this.setState({ downloading: true }); getData .then((data: Array) => { const csv = genCSV(data, fieldsData); download(fileName, csv); }).then(() => { this.setState({ downloading: false }, triggerModal); }); } else { // not support other exportWay for now } } }); } handleCancel = () => { this.props.triggerModal(); } render() { const {selectedValue, visible, fields, form: {getFieldDecorator}, title, intl} = this.props; const {downloading} = this.state; const formItemLayout = { labelCol: { xs: { span: 24 }, sm: { span: 5 }, }, wrapperCol: { xs: { span: 24 }, sm: { span: 12 }, }, }; return ( } visible={visible} footer={null} closable maskClosable onCancel={this.handleCancel} >
} > {getFieldDecorator('exportData', { initialValue: selectedValue.length ? 'SELECTED' : 'ALL', })( {title} )} } > {getFieldDecorator('exportWay', { initialValue: DOWNLOAD, })( )} } > {getFieldDecorator('exportFieldKeys', { initialValue: fields.map(field => field.keyName), })( )}
); } } function genCSV(data: Array, fields: Array) { const fieldNames = fields.map(field => field.title || field.keyName); const rows = [fieldNames]; data.forEach((datum) => { const values = []; fields.forEach((field) => { let value = get(datum, field.keyName); if (field.render) { value = field.render(value); } if (Array.isArray(value)) { value = value.join(';'); } values.push(value); }); rows.push(values); }); let csvContent = 'data:text/csv;charset=utf-8,'; rows.forEach((rowArray) => { const row = rowArray.join(','); csvContent += `${row}\r\n`; }); return csvContent; } function download(fileName, csvContent) { const encodedUri = encodeURI(csvContent); const link = document.createElement('a'); link.setAttribute('href', encodedUri); link.setAttribute('download', `${fileName}.csv`); link.innerHTML = ''; document.body && document.body.appendChild(link); // Required for FF link.click(); }