diff --git a/ui/src/dashboards/actions/v2/views.ts b/ui/src/dashboards/actions/v2/views.ts index 78ef1a9b5d..c9070194bb 100644 --- a/ui/src/dashboards/actions/v2/views.ts +++ b/ui/src/dashboards/actions/v2/views.ts @@ -1,6 +1,6 @@ // Utils import { - readView as readViewAJAX, + getView as getViewAJAX, updateView as updateViewAJAX, } from 'src/dashboards/apis/v2/' @@ -29,12 +29,12 @@ export const setView = ( payload: {id, view, status}, }) -export const readView = (dashboardID: string, cellID: string) => async ( +export const getView = (dashboardID: string, cellID: string) => async ( dispatch: Dispatch ): Promise => { dispatch(setView(cellID, null, RemoteDataState.Loading)) try { - const view = await readViewAJAX(dashboardID, cellID) + const view = await getViewAJAX(dashboardID, cellID) dispatch(setView(cellID, view, RemoteDataState.Done)) } catch { diff --git a/ui/src/dashboards/apis/v2/index.ts b/ui/src/dashboards/apis/v2/index.ts index b958c595e2..12935ae367 100644 --- a/ui/src/dashboards/apis/v2/index.ts +++ b/ui/src/dashboards/apis/v2/index.ts @@ -121,7 +121,7 @@ export const removeDashboardLabels = async ( ) } -export const readView = async ( +export const getView = async ( dashboardID: string, cellID: string ): Promise => { diff --git a/ui/src/dashboards/components/DashboardExportOverlay.tsx b/ui/src/dashboards/components/DashboardExportOverlay.tsx index 76a5870419..adf9b57c9a 100644 --- a/ui/src/dashboards/components/DashboardExportOverlay.tsx +++ b/ui/src/dashboards/components/DashboardExportOverlay.tsx @@ -8,7 +8,7 @@ import ExportOverlay from 'src/shared/components/ExportOverlay' import {dashboardToTemplate} from 'src/shared/utils/resourceToTemplate' // APIs -import {getDashboard} from 'src/dashboards/apis/v2' +import {getDashboard, getView} from 'src/dashboards/apis/v2' interface State { dashboardTemplate: Record @@ -25,9 +25,11 @@ class DashboardExportOverlay extends PureComponent { const { params: {dashboardID}, } = this.props - console.log('loading!?') + const dashboard = await getDashboard(dashboardID) - const dashboardTemplate = dashboardToTemplate(dashboard) + const pendingViews = dashboard.cells.map(c => getView(dashboardID, c.id)) + const views = await Promise.all(pendingViews) + const dashboardTemplate = dashboardToTemplate(dashboard, views) this.setState({dashboardTemplate}) } diff --git a/ui/src/shared/components/cells/Cell.tsx b/ui/src/shared/components/cells/Cell.tsx index 8eab66016b..0aacc4dfd6 100644 --- a/ui/src/shared/components/cells/Cell.tsx +++ b/ui/src/shared/components/cells/Cell.tsx @@ -11,7 +11,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors' import Conditional from 'src/shared/components/Conditional' // Actions -import {readView} from 'src/dashboards/actions/v2/views' +import {getView} from 'src/dashboards/actions/v2/views' // Types import {RemoteDataState, TimeRange} from 'src/types' @@ -26,7 +26,7 @@ interface StateProps { } interface DispatchProps { - onReadView: typeof readView + onGetView: typeof getView } interface PassedProps { @@ -45,11 +45,11 @@ type Props = StateProps & DispatchProps & PassedProps @ErrorHandling class CellComponent extends Component { public async componentDidMount() { - const {viewStatus, cell, onReadView} = this.props + const {viewStatus, cell, onGetView} = this.props if (viewStatus === RemoteDataState.NotStarted) { const dashboardID = cell.dashboardID - onReadView(dashboardID, cell.id) + onGetView(dashboardID, cell.id) } } @@ -144,7 +144,7 @@ const mstp = (state: AppState, ownProps: PassedProps): StateProps => { } const mdtp: DispatchProps = { - onReadView: readView, + onGetView: getView, } export default connect( diff --git a/ui/src/shared/utils/resourceToTemplate.ts b/ui/src/shared/utils/resourceToTemplate.ts index db69e9e295..c5a260a0a0 100644 --- a/ui/src/shared/utils/resourceToTemplate.ts +++ b/ui/src/shared/utils/resourceToTemplate.ts @@ -1,6 +1,6 @@ import _ from 'lodash' import {getDeep} from 'src/utils/wrappers' -import {Task, Label, Dashboard} from 'src/types/v2' +import {Task, Label, Dashboard, Cell, View} from 'src/types/v2' import {ITemplate, TemplateType} from '@influxdata/influx' const CURRENT_TEMPLATE_VERSION = '1' @@ -15,9 +15,6 @@ const blankTaskTemplate = () => { const baseTemplate = blankTemplate() return { ...baseTemplate, - meta: { - ...baseTemplate.meta, - }, content: { ...baseTemplate.content, data: {...baseTemplate.content.data, type: TemplateType.Task}, @@ -36,6 +33,29 @@ const blankTaskTemplate = () => { } } +const blankDashboardTemplate = () => { + const baseTemplate = blankTemplate() + return { + ...baseTemplate, + content: { + ...baseTemplate.content, + data: {...baseTemplate.content.data, type: TemplateType.Dashboard}, + }, + labels: [ + ...baseTemplate.labels, + { + id: '1', + name: 'influx.dashboard', + properties: { + color: 'ffb3b3', + description: + 'This is a template for a dashboard resource on influx 2.0', + }, + }, + ], + } +} + export const labelToRelationship = (l: Label) => { return {type: TemplateType.Label, id: l.id} } @@ -76,7 +96,6 @@ export const taskToTemplate = ( meta: { ...baseTemplate.meta, name: templateName, - version: CURRENT_TEMPLATE_VERSION, description: `template created from task: ${taskName}`, }, content: { @@ -96,8 +115,83 @@ export const taskToTemplate = ( return template } -// Todo: update template to match task format -export const dashboardToTemplate = (dashboard: Dashboard) => ({ - meta: {chronografVersion: '2.0'}, - dashboard, +const viewToIncluded = (view: View) => ({ + type: TemplateType.View, + id: view.id, + attributes: view, }) +const viewToRelationship = (view: View) => ({ + type: TemplateType.View, + id: view.id, +}) + +const cellToIncluded = (cell: Cell, views: View[]) => { + const cellView = views.find(v => v.id === cell.id) + const viewRelationship = viewToRelationship(cellView) + + return { + id: cell.id, + type: TemplateType.Cell, + attributes: cell, + relationships: { + [TemplateType.View]: { + data: viewRelationship, + }, + }, + } +} + +const cellToRelationship = (cell: Cell) => ({ + type: TemplateType.Cell, + id: cell.id, +}) + +export const dashboardToTemplate = ( + dashboard: Dashboard, + views: View[], + baseTemplate = blankDashboardTemplate() +) => { + const dashboardName = _.get(dashboard, 'name', '') + const templateName = `${dashboardName}-Template` + + const dashboardAttributes = _.pick(dashboard, ['name', 'description']) + + const labels = getDeep(dashboard, 'labels', []) + const includedLabels = labels.map(l => labelToIncluded(l)) + const relationshipsLabels = labels.map(l => labelToRelationship(l)) + + const cells = getDeep(dashboard, 'cells', []) + const includedCells = cells.map(c => cellToIncluded(c, views)) + const relationshipsCells = cells.map(c => cellToRelationship(c)) + + const includedViews = views.map(v => viewToIncluded(v)) + + const template = { + ...baseTemplate, + meta: { + ...baseTemplate.meta, + name: templateName, + description: `template created from dashboard: ${dashboardName}`, + }, + content: { + ...baseTemplate.content, + data: { + ...baseTemplate.content.data, + type: TemplateType.Dashboard, + attributes: dashboardAttributes, + relationships: { + [TemplateType.Label]: {data: relationshipsLabels}, + [TemplateType.Cell]: {data: relationshipsCells}, + }, + }, + included: [ + ...baseTemplate.content.included, + ...includedLabels, + ...includedCells, + ...includedViews, + ], + }, + } + + return template +}