Add asset limits getter to DashboardsIndex
parent
20ac4f2357
commit
fbdc65b98d
|
@ -23,10 +23,6 @@ import {
|
|||
updateTimeRangeFromQueryParams,
|
||||
DeleteTimeRangeAction,
|
||||
} from 'src/dashboards/actions/ranges'
|
||||
import {
|
||||
importDashboardSucceeded,
|
||||
importDashboardFailed,
|
||||
} from 'src/shared/copy/notifications'
|
||||
import {setView, SetViewAction, setViews} from 'src/dashboards/actions/views'
|
||||
import {
|
||||
getVariables,
|
||||
|
@ -34,6 +30,7 @@ import {
|
|||
selectValue,
|
||||
} from 'src/variables/actions'
|
||||
import {setExportTemplate} from 'src/templates/actions'
|
||||
import {checkDashboardLimits} from 'src/cloud/actions/limits'
|
||||
|
||||
// Utils
|
||||
import {filterUnusedVars} from 'src/shared/utils/filterUnusedVars'
|
||||
|
@ -246,14 +243,15 @@ export const createDashboardFromTemplate = (
|
|||
const dashboards = await getDashboardsAJAX(org.id)
|
||||
|
||||
dispatch(setDashboards(RemoteDataState.Done, dashboards))
|
||||
dispatch(notify(importDashboardSucceeded()))
|
||||
dispatch(notify(copy.importDashboardSucceeded()))
|
||||
dispatch(checkDashboardLimits())
|
||||
} catch (error) {
|
||||
dispatch(notify(importDashboardFailed(error)))
|
||||
dispatch(notify(copy.importDashboardFailed(error)))
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteDashboardAsync = (dashboard: Dashboard) => async (
|
||||
dispatch: Dispatch<Action>
|
||||
dispatch
|
||||
): Promise<void> => {
|
||||
dispatch(removeDashboard(dashboard.id))
|
||||
dispatch(deleteTimeRange(dashboard.id))
|
||||
|
@ -261,6 +259,7 @@ export const deleteDashboardAsync = (dashboard: Dashboard) => async (
|
|||
try {
|
||||
await deleteDashboardAJAX(dashboard)
|
||||
dispatch(notify(copy.dashboardDeleted(dashboard.name)))
|
||||
dispatch(checkDashboardLimits())
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
notify(copy.dashboardDeleteFailed(dashboard.name, error.data.message))
|
||||
|
|
|
@ -3,47 +3,48 @@ import React, {PureComponent} from 'react'
|
|||
import {InjectedRouter} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
// Decorators
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
// Components
|
||||
import DashboardsIndexContents from 'src/dashboards/components/dashboard_index/DashboardsIndexContents'
|
||||
import {Page} from 'src/pageLayout'
|
||||
import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
|
||||
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
|
||||
import PageTitleWithOrg from 'src/shared/components/PageTitleWithOrg'
|
||||
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
||||
import GetResources, {ResourceTypes} from 'src/shared/components/GetResources'
|
||||
|
||||
// APIs
|
||||
import {createDashboard, cloneDashboard} from 'src/dashboards/apis/'
|
||||
|
||||
// Actions
|
||||
import {
|
||||
getDashboardsAsync,
|
||||
deleteDashboardAsync,
|
||||
updateDashboardAsync,
|
||||
} from 'src/dashboards/actions'
|
||||
import {retainRangesDashTimeV1 as retainRangesDashTimeV1Action} from 'src/dashboards/actions/ranges'
|
||||
import {notify as notifyAction} from 'src/shared/actions/notifications'
|
||||
import GetResources, {ResourceTypes} from 'src/shared/components/GetResources'
|
||||
import {checkDashboardLimits as checkDashboardLimitsAction} from 'src/cloud/actions/limits'
|
||||
|
||||
// Constants
|
||||
import {DEFAULT_DASHBOARD_NAME} from 'src/dashboards/constants/index'
|
||||
import {dashboardCreateFailed} from 'src/shared/copy/notifications'
|
||||
|
||||
// Types
|
||||
import {Notification} from 'src/types/notifications'
|
||||
import {Dashboard, AppState} from 'src/types'
|
||||
|
||||
// Decorators
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||
import {ComponentStatus} from 'src/clockface'
|
||||
|
||||
interface DispatchProps {
|
||||
handleGetDashboards: typeof getDashboardsAsync
|
||||
handleDeleteDashboard: typeof deleteDashboardAsync
|
||||
handleUpdateDashboard: typeof updateDashboardAsync
|
||||
notify: (message: Notification) => void
|
||||
retainRangesDashTimeV1: (dashboardIDs: string[]) => void
|
||||
checkDashboardLimits: typeof checkDashboardLimitsAction
|
||||
notify: typeof notifyAction
|
||||
}
|
||||
|
||||
interface StateProps {
|
||||
dashboards: Dashboard[]
|
||||
limitStatus: LimitStatus
|
||||
}
|
||||
|
||||
interface OwnProps {
|
||||
|
@ -67,15 +68,8 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const {dashboards} = this.props
|
||||
|
||||
const dashboardIDs = dashboards.map(d => d.id)
|
||||
this.props.retainRangesDashTimeV1(dashboardIDs)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {dashboards, notify, handleUpdateDashboard} = this.props
|
||||
const {handleUpdateDashboard, handleDeleteDashboard} = this.props
|
||||
const {searchTerm} = this.state
|
||||
|
||||
return (
|
||||
|
@ -92,30 +86,33 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
onSelectTemplate={this.summonImportFromTemplateOverlay}
|
||||
resourceName="Dashboard"
|
||||
canImportFromTemplate={true}
|
||||
status={this.addResourceStatus}
|
||||
/>
|
||||
</Page.Header.Right>
|
||||
</Page.Header>
|
||||
<Page.Contents fullWidth={false} scrollable={true}>
|
||||
<div className="col-md-12">
|
||||
<GetResources resource={ResourceTypes.Dashboards}>
|
||||
<DashboardsIndexContents
|
||||
filterComponent={() => (
|
||||
<SearchWidget
|
||||
placeholderText="Filter dashboards..."
|
||||
onSearch={this.handleFilterDashboards}
|
||||
<GetResources resource={ResourceTypes.Labels}>
|
||||
<GetAssetLimits>
|
||||
<DashboardsIndexContents
|
||||
filterComponent={() => (
|
||||
<SearchWidget
|
||||
placeholderText="Filter dashboards..."
|
||||
onSearch={this.handleFilterDashboards}
|
||||
searchTerm={searchTerm}
|
||||
/>
|
||||
)}
|
||||
onDeleteDashboard={handleDeleteDashboard}
|
||||
onCreateDashboard={this.handleCreateDashboard}
|
||||
onCloneDashboard={this.handleCloneDashboard}
|
||||
onUpdateDashboard={handleUpdateDashboard}
|
||||
searchTerm={searchTerm}
|
||||
onFilterChange={this.handleFilterDashboards}
|
||||
onImportDashboard={this.summonImportOverlay}
|
||||
/>
|
||||
)}
|
||||
dashboards={dashboards}
|
||||
onDeleteDashboard={this.handleDeleteDashboard}
|
||||
onCreateDashboard={this.handleCreateDashboard}
|
||||
onCloneDashboard={this.handleCloneDashboard}
|
||||
onUpdateDashboard={handleUpdateDashboard}
|
||||
notify={notify}
|
||||
searchTerm={searchTerm}
|
||||
onFilterChange={this.handleFilterDashboards}
|
||||
onImportDashboard={this.summonImportOverlay}
|
||||
/>
|
||||
</GetAssetLimits>
|
||||
</GetResources>
|
||||
</GetResources>
|
||||
</div>
|
||||
</Page.Contents>
|
||||
|
@ -130,6 +127,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
router,
|
||||
notify,
|
||||
params: {orgID},
|
||||
checkDashboardLimits,
|
||||
} = this.props
|
||||
try {
|
||||
const newDashboard = {
|
||||
|
@ -138,6 +136,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
orgID,
|
||||
}
|
||||
const data = await createDashboard(newDashboard)
|
||||
checkDashboardLimits()
|
||||
router.push(`/orgs/${orgID}/dashboards/${data.id}`)
|
||||
} catch (error) {
|
||||
notify(dashboardCreateFailed())
|
||||
|
@ -152,6 +151,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
notify,
|
||||
dashboards,
|
||||
params: {orgID},
|
||||
checkDashboardLimits,
|
||||
} = this.props
|
||||
try {
|
||||
const data = await cloneDashboard(
|
||||
|
@ -163,16 +163,13 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
orgID
|
||||
)
|
||||
router.push(`/orgs/${orgID}/dashboards/${data.id}`)
|
||||
checkDashboardLimits()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
notify(dashboardCreateFailed())
|
||||
}
|
||||
}
|
||||
|
||||
private handleDeleteDashboard = (dashboard: Dashboard) => {
|
||||
this.props.handleDeleteDashboard(dashboard)
|
||||
}
|
||||
|
||||
private handleFilterDashboards = (searchTerm: string): void => {
|
||||
this.setState({searchTerm})
|
||||
}
|
||||
|
@ -192,24 +189,38 @@ class DashboardIndex extends PureComponent<Props, State> {
|
|||
} = this.props
|
||||
router.push(`/orgs/${orgID}/dashboards/import/template`)
|
||||
}
|
||||
|
||||
private get addResourceStatus(): ComponentStatus {
|
||||
const {limitStatus} = this.props
|
||||
if (limitStatus === LimitStatus.EXCEEDED) {
|
||||
return ComponentStatus.Disabled
|
||||
} else {
|
||||
return ComponentStatus.Default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
const {
|
||||
dashboards: {list: dashboards},
|
||||
cloud: {
|
||||
limits: {
|
||||
dashboards: {limitStatus},
|
||||
},
|
||||
},
|
||||
} = state
|
||||
|
||||
return {
|
||||
dashboards,
|
||||
limitStatus,
|
||||
}
|
||||
}
|
||||
|
||||
const mdtp: DispatchProps = {
|
||||
notify: notifyAction,
|
||||
handleGetDashboards: getDashboardsAsync,
|
||||
handleDeleteDashboard: deleteDashboardAsync,
|
||||
handleUpdateDashboard: updateDashboardAsync,
|
||||
retainRangesDashTimeV1: retainRangesDashTimeV1Action,
|
||||
checkDashboardLimits: checkDashboardLimitsAction,
|
||||
}
|
||||
|
||||
export default connect<StateProps, DispatchProps, OwnProps>(
|
||||
|
|
|
@ -1,34 +1,55 @@
|
|||
// Libraries
|
||||
import React, {Component} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import _ from 'lodash'
|
||||
|
||||
// Components
|
||||
import Table from 'src/dashboards/components/dashboard_index/Table'
|
||||
import FilterList from 'src/shared/components/Filter'
|
||||
import GetResources, {ResourceTypes} from 'src/shared/components/GetResources'
|
||||
|
||||
// Actions
|
||||
import {retainRangesDashTimeV1 as retainRangesDashTimeV1Action} from 'src/dashboards/actions/ranges'
|
||||
import {checkDashboardLimits as checkDashboardLimitsAction} from 'src/cloud/actions/limits'
|
||||
|
||||
// Decorators
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
// Types
|
||||
import {Dashboard} from 'src/types'
|
||||
import {Notification} from 'src/types/notifications'
|
||||
import {Dashboard, AppState, RemoteDataState} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
dashboards: Dashboard[]
|
||||
interface OwnProps {
|
||||
onCreateDashboard: () => void
|
||||
onCloneDashboard: (dashboard: Dashboard) => void
|
||||
onDeleteDashboard: (dashboard: Dashboard) => void
|
||||
onUpdateDashboard: (dashboard: Dashboard) => void
|
||||
onFilterChange: (searchTerm: string) => void
|
||||
notify: (message: Notification) => void
|
||||
searchTerm: string
|
||||
filterComponent?: () => JSX.Element
|
||||
onImportDashboard: () => void
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
retainRangesDashTimeV1: typeof retainRangesDashTimeV1Action
|
||||
checkDashboardLimits: typeof checkDashboardLimitsAction
|
||||
}
|
||||
|
||||
interface StateProps {
|
||||
dashboards: Dashboard[]
|
||||
limitStatus: RemoteDataState
|
||||
}
|
||||
|
||||
type Props = DispatchProps & StateProps & OwnProps
|
||||
|
||||
@ErrorHandling
|
||||
export default class DashboardsIndexContents extends Component<Props> {
|
||||
class DashboardsIndexContents extends Component<Props> {
|
||||
public async componentDidMount() {
|
||||
const {dashboards} = this.props
|
||||
|
||||
const dashboardIDs = dashboards.map(d => d.id)
|
||||
this.props.retainRangesDashTimeV1(dashboardIDs)
|
||||
this.props.checkDashboardLimits()
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
onDeleteDashboard,
|
||||
|
@ -43,28 +64,50 @@ export default class DashboardsIndexContents extends Component<Props> {
|
|||
} = this.props
|
||||
|
||||
return (
|
||||
<GetResources resource={ResourceTypes.Labels}>
|
||||
<FilterList<Dashboard>
|
||||
list={dashboards}
|
||||
searchTerm={searchTerm}
|
||||
searchKeys={['name', 'labels[].name']}
|
||||
sortByKey="name"
|
||||
>
|
||||
{filteredDashboards => (
|
||||
<Table
|
||||
searchTerm={searchTerm}
|
||||
filterComponent={filterComponent}
|
||||
dashboards={filteredDashboards}
|
||||
onDeleteDashboard={onDeleteDashboard}
|
||||
onCreateDashboard={onCreateDashboard}
|
||||
onCloneDashboard={onCloneDashboard}
|
||||
onUpdateDashboard={onUpdateDashboard}
|
||||
onFilterChange={onFilterChange}
|
||||
onImportDashboard={onImportDashboard}
|
||||
/>
|
||||
)}
|
||||
</FilterList>
|
||||
</GetResources>
|
||||
<FilterList<Dashboard>
|
||||
list={dashboards}
|
||||
searchTerm={searchTerm}
|
||||
searchKeys={['name', 'labels[].name']}
|
||||
sortByKey="name"
|
||||
>
|
||||
{filteredDashboards => (
|
||||
<Table
|
||||
searchTerm={searchTerm}
|
||||
filterComponent={filterComponent}
|
||||
dashboards={filteredDashboards}
|
||||
onDeleteDashboard={onDeleteDashboard}
|
||||
onCreateDashboard={onCreateDashboard}
|
||||
onCloneDashboard={onCloneDashboard}
|
||||
onUpdateDashboard={onUpdateDashboard}
|
||||
onFilterChange={onFilterChange}
|
||||
onImportDashboard={onImportDashboard}
|
||||
/>
|
||||
)}
|
||||
</FilterList>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state: AppState): StateProps => {
|
||||
const {
|
||||
dashboards: {list: dashboards},
|
||||
cloud: {
|
||||
limits: {status},
|
||||
},
|
||||
} = state
|
||||
|
||||
return {
|
||||
dashboards,
|
||||
limitStatus: status,
|
||||
}
|
||||
}
|
||||
|
||||
const mdtp: DispatchProps = {
|
||||
retainRangesDashTimeV1: retainRangesDashTimeV1Action,
|
||||
checkDashboardLimits: checkDashboardLimitsAction,
|
||||
}
|
||||
|
||||
export default connect<StateProps, DispatchProps, OwnProps>(
|
||||
mstp,
|
||||
mdtp
|
||||
)(DashboardsIndexContents)
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, {PureComponent} from 'react'
|
|||
import _ from 'lodash'
|
||||
|
||||
// Components
|
||||
import {Dropdown, DropdownMode} from 'src/clockface'
|
||||
import {Dropdown, DropdownMode, ComponentStatus} from 'src/clockface'
|
||||
|
||||
// Types
|
||||
import {IconFont, ComponentColor, ComponentSize} from '@influxdata/clockface'
|
||||
|
@ -14,10 +14,12 @@ interface OwnProps {
|
|||
onSelectTemplate?: () => void
|
||||
resourceName: string
|
||||
canImportFromTemplate?: boolean
|
||||
status?: ComponentStatus
|
||||
}
|
||||
|
||||
interface DefaultProps {
|
||||
canImportFromTemplate: boolean
|
||||
status: ComponentStatus
|
||||
}
|
||||
|
||||
type Props = OwnProps & DefaultProps
|
||||
|
@ -25,6 +27,7 @@ type Props = OwnProps & DefaultProps
|
|||
export default class AddResourceDropdown extends PureComponent<Props> {
|
||||
public static defaultProps: DefaultProps = {
|
||||
canImportFromTemplate: false,
|
||||
status: ComponentStatus.Default,
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
@ -37,6 +40,7 @@ export default class AddResourceDropdown extends PureComponent<Props> {
|
|||
buttonSize={ComponentSize.Small}
|
||||
widthPixels={160}
|
||||
onChange={this.handleSelect}
|
||||
status={this.props.status}
|
||||
>
|
||||
{this.optionItems}
|
||||
</Dropdown>
|
||||
|
|
Loading…
Reference in New Issue