Skip to content

Commit

Permalink
Merge pull request #12958 from influxdata/feat/import-variables
Browse files Browse the repository at this point in the history
feat(ui): Create import overlay to import variables
  • Loading branch information
ischolten authored Mar 27, 2019
2 parents 9252677 + d4b3de6 commit d7780e1
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
1. [12888](https://github.com/influxdata/influxdb/pull/12888): Add the ability to delete a template
1. [12901](https://github.com/influxdata/influxdb/pull/12901): Save user preference for variable control bar visibility and default to visible
1. [12910](https://github.com/influxdata/influxdb/pull/12910): Add the ability to clone a template
1. [12958](https://github.com/influxdata/influxdb/pull/12958): Add the ability to import a variable

### Bug Fixes

Expand Down
5 changes: 5 additions & 0 deletions ui/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import OrgTemplatesIndex from 'src/organizations/containers/OrgTemplatesIndex'
import TemplateExportOverlay from 'src/templates/components/TemplateExportOverlay'
import TemplateImportOverlay from 'src/templates/components/TemplateImportOverlay'
import CreateOrgOverlay from './organizations/components/CreateOrgOverlay'
import VariableImportOverlay from 'src/variables/components/VariableImportOverlay'

import OnboardingWizardPage from 'src/onboarding/containers/OnboardingWizardPage'

Expand Down Expand Up @@ -169,6 +170,10 @@ class Root extends PureComponent {
path="variables"
component={OrgVariablesIndex}
>
<Route
path="import"
component={VariableImportOverlay}
/>
<Route
path=":id/export"
component={OrgVariableExportOverlay}
Expand Down
11 changes: 8 additions & 3 deletions ui/src/organizations/components/Variables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, {PureComponent, ChangeEvent} from 'react'
import _ from 'lodash'
import {connect} from 'react-redux'
import {withRouter, WithRouterProps} from 'react-router'

// Utils
import {getVariablesForOrg} from 'src/variables/selectors'
Expand Down Expand Up @@ -43,7 +44,7 @@ interface OwnProps {
org: Organization
}

type Props = StateProps & DispatchProps & OwnProps
type Props = StateProps & DispatchProps & OwnProps & WithRouterProps

interface State {
searchTerm: string
Expand Down Expand Up @@ -153,7 +154,11 @@ class Variables extends PureComponent<Props, State> {

private handleFilterBlur() {}

private handleOpenImportOverlay = (): void => {}
private handleOpenImportOverlay = (): void => {
const {router, org} = this.props

router.push(`/organizations/${org.id}/variables/import`)
}

private handleOpenCreateOverlay = (): void => {
this.setState({createOverlayState: OverlayState.Open})
Expand Down Expand Up @@ -202,4 +207,4 @@ const mdtp = {
export default connect<StateProps, DispatchProps, OwnProps>(
mstp,
mdtp
)(Variables)
)(withRouter<OwnProps>(Variables))
2 changes: 1 addition & 1 deletion ui/src/organizations/containers/OrgTemplatesIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class OrgTemplatesIndex extends Component<Props> {

private handleImport = () => {
const {router, org} = this.props
router.push(`organizations/${org.id}/templates/import`)
router.push(`/organizations/${org.id}/templates/import`)
}
}

Expand Down
6 changes: 3 additions & 3 deletions ui/src/shared/components/ImportOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ enum ImportOption {
Paste = 'paste',
}

interface OwnProps extends WithRouterProps {
interface OwnProps {
onDismissOverlay: () => void
resourceName: string
onSubmit: (importString: string, orgID: string) => void
Expand All @@ -41,7 +41,7 @@ interface State {
orgID: string
}

type Props = StateProps & OwnProps
type Props = StateProps & OwnProps & WithRouterProps

class ImportOverlay extends PureComponent<Props, State> {
public static defaultProps: {isVisible: boolean} = {
Expand Down Expand Up @@ -195,4 +195,4 @@ const mstp = ({orgs}: AppState): StateProps => ({orgs})
export default connect<StateProps, {}, OwnProps>(
mstp,
null
)(withRouter(ImportOverlay))
)(withRouter<OwnProps>(ImportOverlay))
32 changes: 31 additions & 1 deletion ui/src/templates/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TaskTemplate,
TemplateBase,
Task,
VariableTemplate,
} from 'src/types'
import {IDashboard, Cell} from '@influxdata/influx'
import {client} from 'src/utils/api'
Expand Down Expand Up @@ -173,7 +174,7 @@ const createViewsFromTemplate = async (
}

const createVariablesFromTemplate = async (
template: DashboardTemplate,
template: DashboardTemplate | VariableTemplate,
orgID: string
) => {
const {
Expand Down Expand Up @@ -229,3 +230,32 @@ const createTaskLabelsFromTemplate = async (
const templateLabels = await createLabelsFromTemplate(template, task.orgID)
await client.tasks.addLabels(task.id, templateLabels)
}

export const createVariableFromTemplate = async (
template: VariableTemplate,
orgID: string
) => {
const {content} = template

if (
content.data.type !== TemplateType.Variable ||
template.meta.version !== '1'
) {
throw new Error('Can not create variable from this template')
}

const createdVariable = await client.variables.create({
...content.data.attributes,
orgID,
})

if (!createdVariable || !createdVariable.id) {
throw new Error('Failed to create variable from template')
}

await createVariablesFromTemplate(template, orgID)

const variable = await client.variables.get(createdVariable.id)

return variable
}
18 changes: 18 additions & 0 deletions ui/src/types/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export type DashboardTemplateIncluded =
| LabelIncluded
| VariableIncluded

export type VariableTemplateIncluded = LabelIncluded | VariableIncluded

// Template Datas
interface TaskTemplateData extends TemplateData {
type: TemplateType.Task
Expand All @@ -117,6 +119,15 @@ interface DashboardTemplateData extends TemplateData {
}
}

interface VariableTemplateData extends TemplateData {
type: TemplateType.Variable
attributes: Variable
relationships: {
[TemplateType.Label]: {data: LabelRelationship[]}
[TemplateType.Variable]: {data: VariableRelationship[]}
}
}

// Templates
export interface TaskTemplate extends TemplateBase {
content: {
Expand All @@ -132,6 +143,13 @@ export interface DashboardTemplate extends TemplateBase {
}
}

export interface VariableTemplate extends TemplateBase {
content: {
data: VariableTemplateData
included: VariableTemplateIncluded[]
}
}

export type Template = TaskTemplate | DashboardTemplate

export interface TemplateSummary extends DocumentListEntry {
Expand Down
25 changes: 24 additions & 1 deletion ui/src/variables/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
} from 'src/shared/copy/notifications'
import {setExportTemplate} from 'src/templates/actions'

// APIs
import {createVariableFromTemplate as createVariableFromTemplateAJAX} from 'src/templates/api'

// Utils
import {getValueSelections, getVariablesForOrg} from 'src/variables/selectors'
import {WrappedCancelablePromise, CancellationError} from 'src/types/promises'
Expand All @@ -26,7 +29,7 @@ import * as copy from 'src/shared/copy/notifications'

// Types
import {Dispatch} from 'redux-thunk'
import {RemoteDataState} from 'src/types'
import {RemoteDataState, VariableTemplate} from 'src/types'
import {GetState} from 'src/types'
import {Variable} from '@influxdata/influx'
import {VariableValuesByID} from 'src/variables/types'
Expand Down Expand Up @@ -179,6 +182,26 @@ export const createVariable = (variable: Variable) => async (
}
}

export const createVariableFromTemplate = (
template: VariableTemplate,
orgID: string
) => async (dispatch: Dispatch<Action>) => {
try {
const createdVariable = await createVariableFromTemplateAJAX(
template,
orgID
)

dispatch(
setVariable(createdVariable.id, RemoteDataState.Done, createdVariable)
)
dispatch(notify(createVariableSuccess(createdVariable.name)))
} catch (e) {
console.error(e)
dispatch(notify(createVariableFailed(e.response.data.message)))
}
}

export const updateVariable = (id: string, props: Partial<Variable>) => async (
dispatch: Dispatch<Action>
) => {
Expand Down
83 changes: 83 additions & 0 deletions ui/src/variables/components/VariableImportOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React, {PureComponent} from 'react'
import {withRouter, WithRouterProps} from 'react-router'
import {connect} from 'react-redux'

// Components
import ImportOverlay from 'src/shared/components/ImportOverlay'

// Actions
import {
createVariableFromTemplate as createVariableFromTemplateAction,
getVariables as getVariablesAction,
} from 'src/variables/actions'
import {notify as notifyAction} from 'src/shared/actions/notifications'

// Types
import {AppState, Organization} from 'src/types'

interface DispatchProps {
getVariables: typeof getVariablesAction
createVariableFromTemplate: typeof createVariableFromTemplateAction
notify: typeof notifyAction
}

interface StateProps {
org: Organization
}

interface OwnProps extends WithRouterProps {
params: {orgID: string}
}

type Props = DispatchProps & OwnProps & StateProps

class VariableImportOverlay extends PureComponent<Props> {
public render() {
return (
<ImportOverlay
onDismissOverlay={this.onDismiss}
resourceName="Variable"
onSubmit={this.handleImportVariable}
/>
)
}

private onDismiss = () => {
const {router} = this.props

router.goBack()
}

private handleImportVariable = async (
uploadContent: string,
orgID: string
): Promise<void> => {
const {createVariableFromTemplate, getVariables} = this.props

const template = JSON.parse(uploadContent)
await createVariableFromTemplate(template, orgID)

await getVariables()

this.onDismiss()
}
}

const mstp = (state: AppState, props: Props): StateProps => {
const {orgs} = state

const org = orgs.find(o => o.id === props.params.orgID)

return {org}
}

const mdtp: DispatchProps = {
notify: notifyAction,
createVariableFromTemplate: createVariableFromTemplateAction,
getVariables: getVariablesAction,
}

export default connect<StateProps, DispatchProps, Props>(
mstp,
mdtp
)(withRouter(VariableImportOverlay))

0 comments on commit d7780e1

Please sign in to comment.