Skip to content

Commit

Permalink
Merge pull request #12528 from influxdata/feat/export-to-template
Browse files Browse the repository at this point in the history
Add export dashboard to template button to export overlay
  • Loading branch information
ebb-tide authored Mar 12, 2019
2 parents da48330 + c304828 commit 947aade
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 85 deletions.
6 changes: 3 additions & 3 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
},
"dependencies": {
"@influxdata/clockface": "0.0.5",
"@influxdata/influx": "0.2.33",
"@influxdata/influx": "0.2.35",
"@influxdata/react-custom-scrollbars": "4.3.8",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
Expand Down
13 changes: 9 additions & 4 deletions ui/src/dashboards/components/DashboardExportOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ import {dashboardToTemplate} from 'src/shared/utils/resourceToTemplate'
// APIs
import {getDashboard, getView} from 'src/dashboards/apis/v2'

// Types
import {ITemplate} from '@influxdata/influx'

interface State {
dashboardTemplate: Record<string, any>
dashboardTemplate: ITemplate
orgID: string
}

interface Props extends WithRouterProps {
params: {dashboardID: string; orgID: string}
}

class DashboardExportOverlay extends PureComponent<Props, State> {
public state: State = {dashboardTemplate: null}
public state: State = {dashboardTemplate: null, orgID: null}

public async componentDidMount() {
const {
Expand All @@ -31,11 +35,11 @@ class DashboardExportOverlay extends PureComponent<Props, State> {
const views = await Promise.all(pendingViews)
const dashboardTemplate = dashboardToTemplate(dashboard, views)

this.setState({dashboardTemplate})
this.setState({dashboardTemplate, orgID: dashboard.orgID})
}

public render() {
const {dashboardTemplate} = this.state
const {dashboardTemplate, orgID} = this.state
if (!dashboardTemplate) {
return null
}
Expand All @@ -44,6 +48,7 @@ class DashboardExportOverlay extends PureComponent<Props, State> {
resourceName="Dashboard"
resource={dashboardTemplate}
onDismissOverlay={this.onDismiss}
orgID={orgID}
/>
)
}
Expand Down
23 changes: 0 additions & 23 deletions ui/src/dashboards/components/dashboard_index/DashboardsIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/D
import {Page} from 'src/pageLayout'
import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
import ExportOverlay from 'src/shared/components/ExportOverlay'
import ImportDashboardOverlay from 'src/dashboards/components/ImportDashboardOverlay'

// APIs
Expand Down Expand Up @@ -67,8 +66,6 @@ type Props = DispatchProps & StateProps & OwnProps
interface State {
searchTerm: string
isImportingDashboard: boolean
isExportingDashboard: boolean
exportDashboard: Dashboard
}

@ErrorHandling
Expand All @@ -79,8 +76,6 @@ class DashboardIndex extends PureComponent<Props, State> {
this.state = {
searchTerm: '',
isImportingDashboard: false,
isExportingDashboard: false,
exportDashboard: null,
}
}

Expand Down Expand Up @@ -137,7 +132,6 @@ class DashboardIndex extends PureComponent<Props, State> {
</Page.Contents>
</Page>
{this.importOverlay}
{this.exportOverlay}
</>
)
}
Expand Down Expand Up @@ -202,10 +196,6 @@ class DashboardIndex extends PureComponent<Props, State> {
this.setState({isImportingDashboard: !this.state.isImportingDashboard})
}

private handleToggleExportOverlay = (): void => {
this.setState({isExportingDashboard: !this.state.isExportingDashboard})
}

private get importOverlay(): JSX.Element {
const {isImportingDashboard} = this.state
const {orgs} = this.props
Expand All @@ -218,19 +208,6 @@ class DashboardIndex extends PureComponent<Props, State> {
/>
)
}

private get exportOverlay(): JSX.Element {
const {isExportingDashboard, exportDashboard} = this.state

return (
<ExportOverlay
resource={exportDashboard}
isVisible={isExportingDashboard}
resourceName="Dashboard"
onDismissOverlay={this.handleToggleExportOverlay}
/>
)
}
}

const mstp = (state: AppState): StateProps => {
Expand Down
4 changes: 3 additions & 1 deletion ui/src/organizations/components/OrgTaskExportOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {taskToTemplate} from 'src/shared/utils/resourceToTemplate'

// APIs
import {client} from 'src/utils/api'
import {ITemplate} from '@influxdata/influx'
import {Task} from 'src/types/v2'

interface State {
taskTemplate: Record<string, any>
taskTemplate: ITemplate
}

interface Props extends WithRouterProps {
Expand All @@ -38,6 +39,7 @@ class OrgTaskExportOverlay extends PureComponent<Props, State> {
if (!taskTemplate) {
return null
}

return (
<ExportOverlay
resourceName="Task"
Expand Down
80 changes: 69 additions & 11 deletions ui/src/shared/components/ExportOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, {PureComponent} from 'react'
import {connect} from 'react-redux'
import {get} from 'lodash'
import {client} from 'src/utils/api'

// Components
import {
Expand All @@ -12,20 +14,40 @@ import {
import {Button, ComponentColor} from '@influxdata/clockface'
import {Controlled as ReactCodeMirror} from 'react-codemirror2'

// Actions
import {notify as notifyAction} from 'src/shared/actions/notifications'

// Constants
import {
dashboardSavedAsTemplate,
saveDashboardAsTemplateFailed,
} from 'src/shared/copy/notifications'

// Utils
import {downloadTextFile} from 'src/shared/utils/download'
import {addOrgIDToTemplate} from 'src/shared/utils/resourceToTemplate'

// Styles
import 'src/shared/components/ExportOverlay.scss'

interface Props {
// Types
import {ITemplate} from '@influxdata/influx'

interface OwnProps {
onDismissOverlay: () => void
resource: object
resource: ITemplate
orgID: string
resourceName: string
isVisible?: boolean
}

export default class ExportOverlay extends PureComponent<Props> {
interface DispatchProps {
notify: typeof notifyAction
}

type Props = OwnProps & DispatchProps

class ExportOverlay extends PureComponent<Props> {
public static defaultProps: Partial<Props> = {
isVisible: true,
}
Expand Down Expand Up @@ -60,31 +82,67 @@ export default class ExportOverlay extends PureComponent<Props> {
/>
</div>
</OverlayBody>
<OverlayFooter>{this.submitButton}</OverlayFooter>
<OverlayFooter>
{this.downloadButton}
{this.toTemplateButton}
</OverlayFooter>
</OverlayContainer>
</OverlayTechnology>
)
}

private doNothing = () => {}

private get submitButton(): JSX.Element {
const {resourceName} = this.props
private get downloadButton(): JSX.Element {
return (
<Button
text={`Download ${resourceName} as JSON`}
text={`Download JSON`}
onClick={this.handleExport}
color={ComponentColor.Primary}
/>
)
}

private get toTemplateButton(): JSX.Element {
const {resourceName} = this.props
if (resourceName == 'Dashboard') {
return (
<Button
text={`Save as template`}
onClick={this.handleConvertToTemplate}
color={ComponentColor.Primary}
/>
)
}
}

private handleExport = (): void => {
const {resource, resourceName, onDismissOverlay} = this.props
downloadTextFile(
JSON.stringify(resource, null, 1),
`${get(resource, 'name', resourceName)}.json`
)
const name = get(resource, 'name', resourceName)
downloadTextFile(JSON.stringify(resource, null, 1), `${name}.json`)
onDismissOverlay()
}

private handleConvertToTemplate = async (): Promise<void> => {
const {resource, onDismissOverlay, orgID, notify} = this.props

const template = addOrgIDToTemplate(resource, orgID)

try {
await client.templates.create(template)
notify(dashboardSavedAsTemplate())
} catch (error) {
notify(saveDashboardAsTemplateFailed(error))
}
onDismissOverlay()
}
}

const mdtp: DispatchProps = {
notify: notifyAction,
}

export default connect<null, DispatchProps, OwnProps>(
null,
mdtp
)(ExportOverlay)
10 changes: 10 additions & 0 deletions ui/src/shared/copy/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,16 @@ export const importDashboardFailed = (error: string): Notification => ({
message: `Failed to import dashboard: ${error}`,
})

export const dashboardSavedAsTemplate = (): Notification => ({
...defaultSuccessNotification,
message: `Successfully saved dashboard as template.`,
})

export const saveDashboardAsTemplateFailed = (error: string): Notification => ({
...defaultErrorNotification,
message: `Failed to save dashboard as template: ${error}`,
})

// Labels
export const getLabelsFailed = (): Notification => ({
...defaultErrorNotification,
Expand Down
12 changes: 1 addition & 11 deletions ui/src/shared/utils/resourceToTemplate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,7 @@ describe('resourceToTemplate', () => {
},
],
},
labels: [
{
id: '1',
name: 'influx.task',
properties: {
color: 'ffb3b3',
description:
'This is a template for a task resource on influx 2.0',
},
},
],
labels: [],
meta: {
description: 'template created from task: lala',
name: 'lala-Template',
Expand Down
Loading

0 comments on commit 947aade

Please sign in to comment.