Create a seperate function to handle csv downloads from dashboard cells
parent
d060f05274
commit
14a5efac68
|
@ -1,4 +1,4 @@
|
||||||
import resultsToCSV, {formatDate} from 'shared/parsing/resultsToCSV'
|
import {resultsToCSV, formatDate} from 'shared/parsing/resultsToCSV'
|
||||||
|
|
||||||
describe('formatDate', () => {
|
describe('formatDate', () => {
|
||||||
it('converts timestamp to an excel compatible date string', () => {
|
it('converts timestamp to an excel compatible date string', () => {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import classnames from 'classnames'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'
|
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'
|
||||||
import resultsToCSV from 'src/shared/parsing/resultsToCSV.js'
|
import {resultsToCSV} from 'src/shared/parsing/resultsToCSV.js'
|
||||||
import download from 'src/external/download.js'
|
import download from 'src/external/download.js'
|
||||||
|
|
||||||
const getCSV = (query, errorThrown) => async () => {
|
const getCSV = (query, errorThrown) => async () => {
|
||||||
|
|
|
@ -5,6 +5,9 @@ import LayoutCellMenu from 'shared/components/LayoutCellMenu'
|
||||||
import LayoutCellHeader from 'shared/components/LayoutCellHeader'
|
import LayoutCellHeader from 'shared/components/LayoutCellHeader'
|
||||||
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'
|
import {fetchTimeSeriesAsync} from 'shared/actions/timeSeries'
|
||||||
import {removeUnselectedTemplateValues} from 'src/dashboards/constants'
|
import {removeUnselectedTemplateValues} from 'src/dashboards/constants'
|
||||||
|
import {errorThrown} from 'shared/actions/errors'
|
||||||
|
import {dashboardtoCSV} from 'shared/parsing/resultsToCSV'
|
||||||
|
import download from 'src/external/download.js'
|
||||||
|
|
||||||
class LayoutCell extends Component {
|
class LayoutCell extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -32,17 +35,12 @@ class LayoutCell extends Component {
|
||||||
this.props.onSummonOverlayTechnologies(cell)
|
this.props.onSummonOverlayTechnologies(cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDataDownload = cell => async () => {
|
handleCSVDownload = cell => () => {
|
||||||
console.log(cell.name)
|
const {queries, templates} = this.props
|
||||||
const qs = this.props.queries
|
const joined_name = cell.name.split(' ').join('_')
|
||||||
const templates = this.props.templates
|
const resolution = undefined // TODO
|
||||||
const resolution = 740
|
|
||||||
|
|
||||||
if (!qs.length) {
|
const timeSeriesPromises = queries.map(query => {
|
||||||
console.log('empty!') // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeSeriesPromises = qs.map(query => {
|
|
||||||
const {host, database, rp} = query
|
const {host, database, rp} = query
|
||||||
const templatesWithResolution = templates.map(temp => {
|
const templatesWithResolution = templates.map(temp => {
|
||||||
if (temp.tempVar === ':interval:') {
|
if (temp.tempVar === ':interval:') {
|
||||||
|
@ -62,10 +60,16 @@ class LayoutCell extends Component {
|
||||||
resolution,
|
resolution,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Promise.all(timeSeriesPromises).then(timeSeries => {
|
|
||||||
console.log('zomG successfull')
|
Promise.all(timeSeriesPromises).then(results => {
|
||||||
const newSeries = timeSeries.map(response => ({response}))
|
console.log(results)
|
||||||
console.log(newSeries)
|
const CSVString = dashboardtoCSV(results)
|
||||||
|
try {
|
||||||
|
download(CSVString, `${joined_name}.csv`, 'text/plain')
|
||||||
|
} catch (error) {
|
||||||
|
errorThrown(error, 'Unable to download .csv file')
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +83,14 @@ class LayoutCell extends Component {
|
||||||
<div className="dash-graph">
|
<div className="dash-graph">
|
||||||
<LayoutCellMenu
|
<LayoutCellMenu
|
||||||
cell={cell}
|
cell={cell}
|
||||||
|
queriesExist={queries.length}
|
||||||
isDeleting={isDeleting}
|
isDeleting={isDeleting}
|
||||||
isEditable={isEditable}
|
isEditable={isEditable}
|
||||||
onDelete={this.handleDeleteCell}
|
onDelete={this.handleDeleteCell}
|
||||||
onEdit={this.handleSummonOverlay}
|
onEdit={this.handleSummonOverlay}
|
||||||
handleClickOutside={this.closeMenu}
|
handleClickOutside={this.closeMenu}
|
||||||
onDeleteClick={this.handleDeleteClick}
|
onDeleteClick={this.handleDeleteClick}
|
||||||
onDataDownload={this.handleDataDownload}
|
onCSVDownload={this.handleCSVDownload}
|
||||||
/>
|
/>
|
||||||
<LayoutCellHeader
|
<LayoutCellHeader
|
||||||
queries={queries}
|
queries={queries}
|
||||||
|
|
|
@ -2,7 +2,15 @@ import React, {PropTypes} from 'react'
|
||||||
import OnClickOutside from 'react-onclickoutside'
|
import OnClickOutside from 'react-onclickoutside'
|
||||||
|
|
||||||
const LayoutCellMenu = OnClickOutside(
|
const LayoutCellMenu = OnClickOutside(
|
||||||
({isDeleting, onEdit, onDeleteClick, onDelete, onDataDownload, cell}) =>
|
({
|
||||||
|
isDeleting,
|
||||||
|
onEdit,
|
||||||
|
onDeleteClick,
|
||||||
|
onDelete,
|
||||||
|
onCSVDownload,
|
||||||
|
queriesExist,
|
||||||
|
cell,
|
||||||
|
}) =>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
isDeleting
|
isDeleting
|
||||||
|
@ -13,12 +21,14 @@ const LayoutCellMenu = OnClickOutside(
|
||||||
<div className="dash-graph-context--button" onClick={onEdit(cell)}>
|
<div className="dash-graph-context--button" onClick={onEdit(cell)}>
|
||||||
<span className="icon pencil" />
|
<span className="icon pencil" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
{queriesExist
|
||||||
className="dash-graph-context--button"
|
? <div
|
||||||
onClick={onDataDownload(cell)}
|
className="dash-graph-context--button"
|
||||||
>
|
onClick={onCSVDownload(cell)}
|
||||||
<span className="icon download" />
|
>
|
||||||
</div>
|
<span className="icon download" />
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
{isDeleting
|
{isDeleting
|
||||||
? <div className="dash-graph-context--button active">
|
? <div className="dash-graph-context--button active">
|
||||||
<span className="icon trash" />
|
<span className="icon trash" />
|
||||||
|
|
|
@ -4,7 +4,7 @@ import moment from 'moment'
|
||||||
export const formatDate = timestamp =>
|
export const formatDate = timestamp =>
|
||||||
moment(timestamp).format('M/D/YYYY h:mm:ss A')
|
moment(timestamp).format('M/D/YYYY h:mm:ss A')
|
||||||
|
|
||||||
const resultsToCSV = results => {
|
export const resultsToCSV = results => {
|
||||||
if (!_.get(results, ['0', 'series', '0'])) {
|
if (!_.get(results, ['0', 'series', '0'])) {
|
||||||
return {flag: 'no_data', name: '', CSVString: ''}
|
return {flag: 'no_data', name: '', CSVString: ''}
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,24 @@ const resultsToCSV = results => {
|
||||||
return {flag: 'ok', name, CSVString}
|
return {flag: 'ok', name, CSVString}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default resultsToCSV
|
export const dashboardtoCSV = data => {
|
||||||
|
const columnNames = _.flatten(
|
||||||
|
data.map(r => _.get(r, 'results[0].series[0].columns')) // TODO default?
|
||||||
|
)
|
||||||
|
const timeIndices = columnNames
|
||||||
|
.map((e, i) => (e === 'time' ? i : -1))
|
||||||
|
.filter(e => e >= 0)
|
||||||
|
|
||||||
|
let values = data.map(r => _.get(r, 'results[0].series[0].values')) // TODO default?
|
||||||
|
values = _.unzip(values).map(v => _.flatten(v))
|
||||||
|
if (timeIndices) {
|
||||||
|
values.map(v => {
|
||||||
|
timeIndices.forEach(i => (v[i] = formatDate(v[i])))
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const CSVString = [columnNames.join(',')]
|
||||||
|
.concat(values.map(v => v.join(',')))
|
||||||
|
.join('\n')
|
||||||
|
return CSVString
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue