Merge pull request #4445 from influxdata/enhancement/export-flux-cells

Provide flux services to dashboard export
pull/4446/head
Brandon Farmer 2018-09-13 10:44:49 -07:00 committed by GitHub
commit fbb2dbca8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 18 deletions

View File

@ -21,6 +21,7 @@
1. [#4404](https://github.com/influxdata/chronograf/pull/4404): Add loading status indicator to hosts page
1. [#4422](https://github.com/influxdata/chronograf/pull/4422): Allow deep linking flux script in data explorer
1. [#4410](https://github.com/influxdata/chronograf/pull/4410): Add ability to use line graph visualizations for flux query
1. [#4445](https://github.com/influxdata/chronograf/pull/4445): Allow flux dashboard cells to be exported
### UI Improvements

View File

@ -8,6 +8,7 @@ import DashboardsContents from 'src/dashboards/components/DashboardsPageContents
import {Page} from 'src/reusable_ui'
import {getDeep} from 'src/utils/wrappers'
import {mapDashboardForDownload} from 'src/dashboards/utils/export'
import {createDashboard} from 'src/dashboards/apis'
import {
getDashboardsAsync,
@ -17,6 +18,7 @@ import {
retainRangesDashTimeV1 as retainRangesDashTimeV1Action,
} from 'src/dashboards/actions'
import {notify as notifyAction} from 'src/shared/actions/notifications'
import {fetchAllFluxServicesAsync} from 'src/shared/actions/services'
import {
NEW_DASHBOARD,
@ -29,7 +31,7 @@ import {
notifyDashboardExportFailed,
} from 'src/shared/copy/notifications'
import {Source, Dashboard, RemoteDataState} from 'src/types'
import {Source, Dashboard, RemoteDataState, Service} from 'src/types'
import {Notification} from 'src/types/notifications'
import {DashboardFile, Cell} from 'src/types/dashboards'
@ -37,13 +39,16 @@ export interface Props {
source: Source
sources: Source[]
router: InjectedRouter
dashboard: Dashboard
handleGetDashboards: () => Promise<Dashboard[]>
handleGetChronografVersion: () => string
handleDeleteDashboard: (dashboard: Dashboard) => void
handleImportDashboard: (dashboard: Dashboard) => void
notify: (message: Notification) => void
retainRangesDashTimeV1: (dashboardIDs: number[]) => void
fetchAllFluxServices: (sources: Source[]) => Promise<void>
dashboards: Dashboard[]
services: Service[]
}
interface State {
@ -66,6 +71,8 @@ export class DashboardsPage extends PureComponent<Props, State> {
try {
dashboards = await this.props.handleGetDashboards()
await this.props.fetchAllFluxServices(this.props.sources)
const dashboardIDs = dashboards.map(d => d.id)
this.props.retainRangesDashTimeV1(dashboardIDs)
@ -155,22 +162,10 @@ export class DashboardsPage extends PureComponent<Props, State> {
private modifyDashboardForDownload = async (
dashboard: Dashboard
): Promise<DashboardFile> => {
const {sources} = this.props
const sourceMappings = _.reduce(
sources,
(acc, s) => {
const {name, id, links} = s
const link = _.get(links, 'self', '')
acc[id] = {name, link}
return acc
},
{}
)
const version = await this.props.handleGetChronografVersion()
return {
meta: {chronografVersion: version, sources: sourceMappings},
dashboard,
}
const {sources, services, handleGetChronografVersion} = this.props
const version = await handleGetChronografVersion()
return mapDashboardForDownload(sources, services, dashboard, version)
}
private handleImportDashboard = async (
@ -191,10 +186,15 @@ export class DashboardsPage extends PureComponent<Props, State> {
}
}
const mapStateToProps = ({dashboardUI: {dashboards, dashboard}, sources}) => ({
const mapStateToProps = ({
dashboardUI: {dashboards, dashboard},
sources,
services,
}): Partial<Props> => ({
dashboards,
dashboard,
sources,
services,
})
const mapDispatchToProps = {
@ -204,6 +204,7 @@ const mapDispatchToProps = {
handleImportDashboard: importDashboardAsync,
notify: notifyAction,
retainRangesDashTimeV1: retainRangesDashTimeV1Action,
fetchAllFluxServices: fetchAllFluxServicesAsync,
}
export default withRouter(

View File

@ -0,0 +1,86 @@
import _ from 'lodash'
import {Source, Dashboard, Service, Cell} from 'src/types'
import {CellQuery} from 'src/types/dashboards'
import {DashboardFile} from 'src/types/dashboards'
export const isFluxService = (link: string) => link.includes('service')
export const mapServicesForDownload = (originalServices: Service[]) =>
_.reduce(
originalServices,
(acc, service) => {
const {name, id, links, sourceID} = service
const link = _.get(links, 'self', '')
acc[id] = {name, link, sourceID}
return acc
},
{}
)
export const mapSourcesForDownload = (originalSources: Source[]) =>
_.reduce(
originalSources,
(acc, source) => {
const {name, id, links} = source
const link = _.get(links, 'self', '')
acc[id] = {name, link}
return acc
},
{}
)
export const matchSourceLink = (cellQuery: CellQuery) => {
if (!isFluxService(cellQuery.source)) {
return cellQuery.source
}
return null
}
export const matchServiceLink = (cellQuery: CellQuery) => {
if (isFluxService(cellQuery.source)) {
return cellQuery.source
}
return null
}
export const mapQueriesToSources = (queries: CellQuery[]) => {
return queries.map(query => {
return {
...query,
source: matchSourceLink(query),
service: matchServiceLink(query),
}
})
}
export const mapCellsToSources = (cells: Cell[]) => {
return cells.map(cell => {
const {queries} = cell
return {
...cell,
queries: mapQueriesToSources(queries),
}
})
}
export const mapDashboardForDownload = (
originalSources: Source[],
originalServices: Service[],
originalDashboard: Dashboard,
chronografVersion: string
): DashboardFile => {
const sources = mapSourcesForDownload(originalSources)
const services = mapServicesForDownload(originalServices)
const meta = {chronografVersion, sources, services}
const dashboard = {
...originalDashboard,
cells: mapCellsToSources(originalDashboard.cells),
}
return {meta, dashboard}
}