Merge pull request #12608 from influxdata/dashboard-import-routes

Dashboard import routes
pull/12621/head
Deniz Kusefoglu 2019-03-13 18:26:39 -07:00 committed by GitHub
commit a9cc62778b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 178 deletions

View File

@ -0,0 +1,83 @@
// Libraries
import React, {PureComponent} from 'react'
import {withRouter, WithRouterProps} from 'react-router'
import _ from 'lodash'
import {connect} from 'react-redux'
// Actions
import {getDashboardsAsync} from 'src/dashboards/actions/v2'
import {createDashboardFromTemplate as createDashboardFromTemplateAction} from 'src/dashboards/actions/v2'
// Types
import ImportOverlay from 'src/shared/components/ImportOverlay'
import {AppState, Organization} from 'src/types/v2'
interface DispatchProps {
createDashboardFromTemplate: typeof createDashboardFromTemplateAction
populateDashboards: typeof getDashboardsAsync
}
interface StateProps {
orgs: Organization[]
}
interface OwnProps extends WithRouterProps {
params: {orgID: string}
}
type Props = OwnProps & StateProps & DispatchProps
class DashboardImportOverlay extends PureComponent<Props> {
public render() {
return (
<ImportOverlay
isVisible={true}
onDismissOverlay={this.onDismiss}
resourceName="Dashboard"
onSubmit={this.handleImportDashboard}
/>
)
}
private handleImportDashboard = async (
uploadContent: string
): Promise<void> => {
const {
createDashboardFromTemplate,
populateDashboards,
params: {orgID},
orgs,
} = this.props
const template = JSON.parse(uploadContent)
if (_.isEmpty(template)) {
this.onDismiss()
}
await createDashboardFromTemplate(template, orgID || orgs[0].id)
await populateDashboards()
this.onDismiss()
}
private onDismiss = (): void => {
const {router} = this.props
router.goBack()
}
}
const mdtp: DispatchProps = {
createDashboardFromTemplate: createDashboardFromTemplateAction,
populateDashboards: getDashboardsAsync,
}
const mstp = (state: AppState): StateProps => {
const {orgs} = state
return {orgs}
}
export default connect<StateProps, DispatchProps, OwnProps>(
mstp,
mdtp
)(withRouter(DashboardImportOverlay))

View File

@ -1,79 +0,0 @@
// Libraries
import React, {PureComponent} from 'react'
import _ from 'lodash'
import {connect} from 'react-redux'
// Constants
import {dashboardImportFailed} from 'src/shared/copy/notifications'
// Actions
import {notify as notifyAction} from 'src/shared/actions/notifications'
import {getDashboardsAsync} from 'src/dashboards/actions/v2'
// Types
import ImportOverlay from 'src/shared/components/ImportOverlay'
import {createDashboardFromTemplate as createDashboardFromTemplateAction} from 'src/dashboards/actions/v2'
interface OwnProps {
onDismissOverlay: () => void
isVisible: boolean
}
interface DispatchProps {
notify: typeof notifyAction
createDashboardFromTemplate: typeof createDashboardFromTemplateAction
populateDashboards: typeof getDashboardsAsync
}
type Props = OwnProps & DispatchProps
class ImportDashboardOverlay extends PureComponent<Props> {
constructor(props: Props) {
super(props)
}
public render() {
const {isVisible, onDismissOverlay} = this.props
return (
<ImportOverlay
isVisible={isVisible}
onDismissOverlay={onDismissOverlay}
resourceName="Dashboard"
onSubmit={this.handleUploadDashboard}
/>
)
}
private handleUploadDashboard = async (
uploadContent: string,
orgID: string
): Promise<void> => {
const {
notify,
createDashboardFromTemplate,
onDismissOverlay,
populateDashboards,
} = this.props
try {
const template = JSON.parse(uploadContent)
await createDashboardFromTemplate(template, orgID)
await populateDashboards()
onDismissOverlay()
} catch (error) {
notify(dashboardImportFailed(error))
}
}
}
const mdtp: DispatchProps = {
notify: notifyAction,
createDashboardFromTemplate: createDashboardFromTemplateAction,
populateDashboards: getDashboardsAsync,
}
export default connect<{}, DispatchProps, OwnProps>(
null,
mdtp
)(ImportDashboardOverlay)

View File

@ -8,7 +8,6 @@ import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/D
import {Page} from 'src/pageLayout' import {Page} from 'src/pageLayout'
import SearchWidget from 'src/shared/components/search_widget/SearchWidget' import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown' import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
import ImportDashboardOverlay from 'src/dashboards/components/ImportDashboardOverlay'
// APIs // APIs
import {createDashboard, cloneDashboard} from 'src/dashboards/apis/v2/' import {createDashboard, cloneDashboard} from 'src/dashboards/apis/v2/'
@ -64,7 +63,6 @@ type Props = DispatchProps & StateProps & OwnProps
interface State { interface State {
searchTerm: string searchTerm: string
isImportingDashboard: boolean
} }
@ErrorHandling @ErrorHandling
@ -74,7 +72,6 @@ class DashboardIndex extends PureComponent<Props, State> {
this.state = { this.state = {
searchTerm: '', searchTerm: '',
isImportingDashboard: false,
} }
} }
@ -99,7 +96,7 @@ class DashboardIndex extends PureComponent<Props, State> {
<Page.Header.Right> <Page.Header.Right>
<AddResourceDropdown <AddResourceDropdown
onSelectNew={this.handleCreateDashboard} onSelectNew={this.handleCreateDashboard}
onSelectImport={this.handleToggleImportOverlay} onSelectImport={this.summonImportOverlay}
resourceName="Dashboard" resourceName="Dashboard"
/> />
</Page.Header.Right> </Page.Header.Right>
@ -130,7 +127,7 @@ class DashboardIndex extends PureComponent<Props, State> {
</div> </div>
</Page.Contents> </Page.Contents>
</Page> </Page>
{this.importOverlay} {this.props.children}
</> </>
) )
} }
@ -191,19 +188,9 @@ class DashboardIndex extends PureComponent<Props, State> {
this.setState({searchTerm}) this.setState({searchTerm})
} }
private handleToggleImportOverlay = (): void => { private summonImportOverlay = (): void => {
this.setState({isImportingDashboard: !this.state.isImportingDashboard}) const {router} = this.props
} router.push(`/dashboards/import`)
private get importOverlay(): JSX.Element {
const {isImportingDashboard} = this.state
return (
<ImportDashboardOverlay
onDismissOverlay={this.handleToggleImportOverlay}
isVisible={isImportingDashboard}
/>
)
} }
} }

View File

@ -30,6 +30,7 @@ import TaskEditPage from 'src/tasks/containers/TaskEditPage'
import DashboardPage from 'src/dashboards/components/DashboardPage' import DashboardPage from 'src/dashboards/components/DashboardPage'
import DashboardsIndex from 'src/dashboards/components/dashboard_index/DashboardsIndex' import DashboardsIndex from 'src/dashboards/components/dashboard_index/DashboardsIndex'
import DashboardExportOverlay from 'src/dashboards/components/DashboardExportOverlay' import DashboardExportOverlay from 'src/dashboards/components/DashboardExportOverlay'
import DashboardImportOverlay from 'src/dashboards/components/DashboardImportOverlay'
import DataExplorerPage from 'src/dataExplorer/components/DataExplorerPage' import DataExplorerPage from 'src/dataExplorer/components/DataExplorerPage'
import {MePage, Account} from 'src/me' import {MePage, Account} from 'src/me'
import NotFound from 'src/shared/components/NotFound' import NotFound from 'src/shared/components/NotFound'
@ -114,12 +115,18 @@ class Root extends PureComponent {
<IndexRoute component={OrganizationsIndex} /> <IndexRoute component={OrganizationsIndex} />
<Route path=":orgID"> <Route path=":orgID">
<Route path="buckets" component={OrgBucketIndex} /> <Route path="buckets" component={OrgBucketIndex} />
<Route path="dashboards"> <Route
<IndexRoute component={OrgDashboardsIndex} /> path="dashboards"
component={OrgDashboardsIndex}
>
<Route <Route
path=":dashboardID/export" path=":dashboardID/export"
component={DashboardExportOverlay} component={DashboardExportOverlay}
/> />
<Route
path="import"
component={DashboardImportOverlay}
/>
</Route> </Route>
<Route path="members" component={OrgMembersIndex} /> <Route path="members" component={OrgMembersIndex} />
<Route <Route
@ -165,17 +172,20 @@ class Root extends PureComponent {
path="data-explorer" path="data-explorer"
component={DataExplorerPage} component={DataExplorerPage}
/> />
<Route path="dashboards"> <Route path="dashboards" component={DashboardsIndex}>
<IndexRoute component={DashboardsIndex} />
<Route
path=":dashboardID"
component={DashboardPage}
/>
<Route <Route
path=":dashboardID/export" path=":dashboardID/export"
component={DashboardExportOverlay} component={DashboardExportOverlay}
/> />
<Route
path="import"
component={DashboardImportOverlay}
/>
</Route> </Route>
<Route
path="dashboards/:dashboardID"
component={DashboardPage}
/>
<Route path="me" component={MePage} /> <Route path="me" component={MePage} />
<Route path="account/:tab" component={Account} /> <Route path="account/:tab" component={Account} />
<Route <Route

View File

@ -8,7 +8,6 @@ import _ from 'lodash'
import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/DashboardsIndexContents' import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/DashboardsIndexContents'
import {Input, Tabs} from 'src/clockface' import {Input, Tabs} from 'src/clockface'
import {IconFont} from '@influxdata/clockface' import {IconFont} from '@influxdata/clockface'
import ImportDashboardOverlay from 'src/dashboards/components/ImportDashboardOverlay'
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown' import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
// APIs // APIs
@ -71,7 +70,6 @@ type Props = DispatchProps & StateProps & OwnProps & WithRouterProps
interface State { interface State {
searchTerm: string searchTerm: string
isImportingDashboard: boolean
isEditingDashboardLabels: boolean isEditingDashboardLabels: boolean
dashboardLabelsEdit: Dashboard dashboardLabelsEdit: Dashboard
} }
@ -83,7 +81,6 @@ class Dashboards extends PureComponent<Props, State> {
this.state = { this.state = {
searchTerm: '', searchTerm: '',
isImportingDashboard: false,
isEditingDashboardLabels: false, isEditingDashboardLabels: false,
dashboardLabelsEdit: null, dashboardLabelsEdit: null,
} }
@ -115,7 +112,7 @@ class Dashboards extends PureComponent<Props, State> {
/> />
<AddResourceDropdown <AddResourceDropdown
onSelectNew={this.handleCreateDashboard} onSelectNew={this.handleCreateDashboard}
onSelectImport={this.handleToggleOverlay} onSelectImport={this.handleImport}
resourceName="Dashboard" resourceName="Dashboard"
/> />
</Tabs.TabContentsHeader> </Tabs.TabContentsHeader>
@ -133,7 +130,6 @@ class Dashboards extends PureComponent<Props, State> {
showOwnerColumn={false} showOwnerColumn={false}
onFilterChange={this.handleFilterUpdate} onFilterChange={this.handleFilterUpdate}
/> />
{this.renderImportOverlay}
</> </>
) )
} }
@ -149,6 +145,12 @@ class Dashboards extends PureComponent<Props, State> {
private handleFilterUpdate = (searchTerm: string): void => { private handleFilterUpdate = (searchTerm: string): void => {
this.setState({searchTerm}) this.setState({searchTerm})
} }
private handleImport = (): void => {
const {router, params} = this.props
router.push(`/organizations/${params.orgID}/dashboards/import`)
}
private handleSetDefaultDashboard = async ( private handleSetDefaultDashboard = async (
defaultDashboardLink: string defaultDashboardLink: string
): Promise<void> => { ): Promise<void> => {
@ -200,21 +202,6 @@ class Dashboards extends PureComponent<Props, State> {
private handleDeleteDashboard = (dashboard: Dashboard) => { private handleDeleteDashboard = (dashboard: Dashboard) => {
this.props.handleDeleteDashboard(dashboard) this.props.handleDeleteDashboard(dashboard)
} }
private handleToggleOverlay = (): void => {
this.setState({isImportingDashboard: !this.state.isImportingDashboard})
}
private get renderImportOverlay(): JSX.Element {
const {isImportingDashboard} = this.state
return (
<ImportDashboardOverlay
onDismissOverlay={this.handleToggleOverlay}
isVisible={isImportingDashboard}
/>
)
}
} }
const mstp = (state: AppState): StateProps => { const mstp = (state: AppState): StateProps => {
@ -242,4 +229,4 @@ const mdtp: DispatchProps = {
export default connect<StateProps, DispatchProps, OwnProps>( export default connect<StateProps, DispatchProps, OwnProps>(
mstp, mstp,
mdtp mdtp
)(withRouter<OwnProps>(Dashboards)) )(withRouter(Dashboards))

View File

@ -7,17 +7,11 @@ import {get} from 'lodash'
import ImportOverlay from 'src/shared/components/ImportOverlay' import ImportOverlay from 'src/shared/components/ImportOverlay'
// Actions // Actions
import {notify as notifyAction} from 'src/shared/actions/notifications'
import {createTaskFromTemplate as createTaskFromTemplateAction} from 'src/organizations/actions/orgView' import {createTaskFromTemplate as createTaskFromTemplateAction} from 'src/organizations/actions/orgView'
import {getTasks as getTasksAction} from 'src/organizations/actions/orgView' import {getTasks as getTasksAction} from 'src/organizations/actions/orgView'
import {populateTasks as populateTasksAction} from 'src/tasks/actions/v2' import {populateTasks as populateTasksAction} from 'src/tasks/actions/v2'
import {
importTaskFailed,
importTaskSucceeded,
} from 'src/shared/copy/notifications'
interface DispatchProps { interface DispatchProps {
notify: typeof notifyAction
createTaskFromTemplate: typeof createTaskFromTemplateAction createTaskFromTemplate: typeof createTaskFromTemplateAction
getTasks: typeof getTasksAction getTasks: typeof getTasksAction
populateTasks: typeof populateTasksAction populateTasks: typeof populateTasksAction
@ -50,7 +44,7 @@ class TaskImportOverlay extends PureComponent<Props> {
importString: string, importString: string,
orgID: string orgID: string
): Promise<void> => { ): Promise<void> => {
const {createTaskFromTemplate, getTasks, populateTasks, notify} = this.props const {createTaskFromTemplate, getTasks, populateTasks} = this.props
try { try {
const template = JSON.parse(importString) const template = JSON.parse(importString)
@ -64,17 +58,13 @@ class TaskImportOverlay extends PureComponent<Props> {
// import overlay is in tasks view // import overlay is in tasks view
populateTasks() populateTasks()
} }
} catch (error) {}
this.onDismiss() this.onDismiss()
notify(importTaskSucceeded())
} catch (error) {
notify(importTaskFailed(error))
}
} }
} }
const mdtp: DispatchProps = { const mdtp: DispatchProps = {
notify: notifyAction,
createTaskFromTemplate: createTaskFromTemplateAction, createTaskFromTemplate: createTaskFromTemplateAction,
getTasks: getTasksAction, getTasks: getTasksAction,
populateTasks: populateTasksAction, populateTasks: populateTasksAction,

View File

@ -43,14 +43,11 @@ type Props = WithRouterProps & RouterProps & DispatchProps & StateProps
@ErrorHandling @ErrorHandling
class OrgDashboardsIndex extends Component<Props> { class OrgDashboardsIndex extends Component<Props> {
constructor(props) {
super(props)
}
public render() { public render() {
const {org} = this.props const {org} = this.props
return ( return (
<>
<Page titleTag={org.name}> <Page titleTag={org.name}>
<OrgHeader orgID={org.id} /> <OrgHeader orgID={org.id} />
<Page.Contents fullWidth={false} scrollable={true}> <Page.Contents fullWidth={false} scrollable={true}>
@ -87,6 +84,8 @@ class OrgDashboardsIndex extends Component<Props> {
</div> </div>
</Page.Contents> </Page.Contents>
</Page> </Page>
{this.props.children}
</>
) )
} }
} }