Merge pull request #4445 from influxdata/enhancement/export-flux-cells
Provide flux services to dashboard exportpull/4446/head
commit
fbb2dbca8d
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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}
|
||||
}
|
Loading…
Reference in New Issue