feat(ui): redesign asset & rate limit alerts (#19032)
* feat(ui): update rate limit alert * feat(ui): update to clockface 2.3.0 * feat(ui): update limit alert components * feat(ui): add home page limit alert * feat(ui): replace alert page limit alerts * feat(ui): relace load data limit alerts * feat(ui): replace dashboards limit alerts * feat(ui): replace data explorer limit alerts * feat(ui): replace tasks limit alerts * feat(ui): replace settings limit alerts * fix(ui): prettier * feat(ui): update changelog * fix(ui): update clockface to 2.3.1 and fix tests * fix(ui): change test idpull/19055/head
parent
17391d6924
commit
4df52d0cb4
|
@ -21,6 +21,7 @@
|
||||||
1. [19029](https://github.com/influxdata/influxdb/pull/19029): Navigating away from a dashboard cancels all pending queries
|
1. [19029](https://github.com/influxdata/influxdb/pull/19029): Navigating away from a dashboard cancels all pending queries
|
||||||
1. [19003](https://github.com/influxdata/influxdb/pull/19003): Upgrade to Flux v0.74.0
|
1. [19003](https://github.com/influxdata/influxdb/pull/19003): Upgrade to Flux v0.74.0
|
||||||
1. [19040](https://github.com/influxdata/influxdb/pull/19040): Drop the REPL command from influx CLI
|
1. [19040](https://github.com/influxdata/influxdb/pull/19040): Drop the REPL command from influx CLI
|
||||||
|
1. [19032](https://github.com/influxdata/influxdb/pull/19032): Redesign asset & rate limit alerts
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
|
@ -802,12 +802,12 @@ describe('DataExplorer', () => {
|
||||||
cy.getByTestID('raw-data--toggle').click()
|
cy.getByTestID('raw-data--toggle').click()
|
||||||
|
|
||||||
cy.get('.time-machine--view').within(() => {
|
cy.get('.time-machine--view').within(() => {
|
||||||
cy.get('.cf-dapper-scrollbars--thumb-y') // TODO(zoe): replace with test ids https://github.com/influxdata/clockface/issues/507
|
cy.getByTestID('rawdata-table--scrollbar--thumb-y')
|
||||||
.trigger('mousedown', {force: true})
|
.trigger('mousedown', {force: true})
|
||||||
.trigger('mousemove', {clientY: 5000})
|
.trigger('mousemove', {clientY: 5000})
|
||||||
.trigger('mouseup')
|
.trigger('mouseup')
|
||||||
|
|
||||||
cy.get('.cf-dapper-scrollbars--thumb-x') // TODO(zoe): replace with test ids https://github.com/influxdata/clockface/issues/507
|
cy.getByTestID('rawdata-table--scrollbar--thumb-x')
|
||||||
.trigger('mousedown', {force: true})
|
.trigger('mousedown', {force: true})
|
||||||
.trigger('mousemove', {clientX: 1000})
|
.trigger('mousemove', {clientX: 1000})
|
||||||
.trigger('mouseup')
|
.trigger('mouseup')
|
||||||
|
@ -831,7 +831,7 @@ describe('DataExplorer', () => {
|
||||||
cy.getByTestID(`view-type--table`).click()
|
cy.getByTestID(`view-type--table`).click()
|
||||||
|
|
||||||
cy.get('.time-machine--view').within(() => {
|
cy.get('.time-machine--view').within(() => {
|
||||||
cy.get('.cf-dapper-scrollbars--thumb-y') // TODO(zoe): replace with test ids https://github.com/influxdata/clockface/issues/507
|
cy.getByTestID('dapper-scrollbars--thumb-y')
|
||||||
.trigger('mousedown', {force: true})
|
.trigger('mousedown', {force: true})
|
||||||
.trigger('mousemove', {clientY: 5000})
|
.trigger('mousemove', {clientY: 5000})
|
||||||
.trigger('mouseup')
|
.trigger('mouseup')
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
"webpack-merge": "^4.2.1"
|
"webpack-merge": "^4.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/clockface": "2.2.0",
|
"@influxdata/clockface": "2.3.1",
|
||||||
"@influxdata/flux": "^0.5.1",
|
"@influxdata/flux": "^0.5.1",
|
||||||
"@influxdata/flux-lsp-browser": "^0.5.11",
|
"@influxdata/flux-lsp-browser": "^0.5.11",
|
||||||
"@influxdata/giraffe": "0.23.0",
|
"@influxdata/giraffe": "0.23.0",
|
||||||
|
|
|
@ -9,7 +9,7 @@ import EventTable from 'src/eventViewer/components/EventTable'
|
||||||
import AlertHistoryControls from 'src/alerting/components/AlertHistoryControls'
|
import AlertHistoryControls from 'src/alerting/components/AlertHistoryControls'
|
||||||
import AlertHistoryQueryParams from 'src/alerting/components/AlertHistoryQueryParams'
|
import AlertHistoryQueryParams from 'src/alerting/components/AlertHistoryQueryParams'
|
||||||
import GetResources from 'src/resources/components/GetResources'
|
import GetResources from 'src/resources/components/GetResources'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {
|
import {
|
||||||
|
@ -80,7 +80,7 @@ const AlertHistoryIndex: FC<Props> = ({
|
||||||
title="Check Statuses"
|
title="Check Statuses"
|
||||||
testID="alert-history-title"
|
testID="alert-history-title"
|
||||||
/>
|
/>
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.ControlBar fullWidth={true}>
|
<Page.ControlBar fullWidth={true}>
|
||||||
<AlertHistoryQueryParams
|
<AlertHistoryQueryParams
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {FunctionComponent, useState} from 'react'
|
import React, {FunctionComponent, useState} from 'react'
|
||||||
import {connect} from 'react-redux'
|
|
||||||
import {Switch, Route} from 'react-router-dom'
|
import {Switch, Route} from 'react-router-dom'
|
||||||
|
|
||||||
//Components
|
//Components
|
||||||
|
@ -9,9 +8,8 @@ import ChecksColumn from 'src/checks/components/ChecksColumn'
|
||||||
import RulesColumn from 'src/notifications/rules/components/RulesColumn'
|
import RulesColumn from 'src/notifications/rules/components/RulesColumn'
|
||||||
import EndpointsColumn from 'src/notifications/endpoints/components/EndpointsColumn'
|
import EndpointsColumn from 'src/notifications/endpoints/components/EndpointsColumn'
|
||||||
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
||||||
import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
import GetResources from 'src/resources/components/GetResources'
|
import GetResources from 'src/resources/components/GetResources'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
|
||||||
import NewThresholdCheckEO from 'src/checks/components/NewThresholdCheckEO'
|
import NewThresholdCheckEO from 'src/checks/components/NewThresholdCheckEO'
|
||||||
import NewDeadmanCheckEO from 'src/checks/components/NewDeadmanCheckEO'
|
import NewDeadmanCheckEO from 'src/checks/components/NewDeadmanCheckEO'
|
||||||
import EditCheckEO from 'src/checks/components/EditCheckEO'
|
import EditCheckEO from 'src/checks/components/EditCheckEO'
|
||||||
|
@ -22,28 +20,15 @@ import EditEndpointOverlay from 'src/notifications/endpoints/components/EditEndp
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
||||||
import {
|
|
||||||
extractMonitoringLimitStatus,
|
|
||||||
extractLimitedMonitoringResources,
|
|
||||||
} from 'src/cloud/utils/limits'
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {AppState, ResourceType} from 'src/types'
|
import {ResourceType} from 'src/types'
|
||||||
import {LimitStatus} from 'src/cloud/actions/limits'
|
|
||||||
|
|
||||||
const alertsPath = '/orgs/:orgID/alerting'
|
const alertsPath = '/orgs/:orgID/alerting'
|
||||||
|
|
||||||
interface StateProps {
|
|
||||||
limitStatus: LimitStatus
|
|
||||||
limitedResources: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActiveColumn = 'checks' | 'endpoints' | 'rules'
|
type ActiveColumn = 'checks' | 'endpoints' | 'rules'
|
||||||
|
|
||||||
const AlertingIndex: FunctionComponent<StateProps> = ({
|
const AlertingIndex: FunctionComponent = () => {
|
||||||
limitStatus,
|
|
||||||
limitedResources,
|
|
||||||
}) => {
|
|
||||||
const [activeColumn, setActiveColumn] = useState<ActiveColumn>('checks')
|
const [activeColumn, setActiveColumn] = useState<ActiveColumn>('checks')
|
||||||
|
|
||||||
const pageContentsClassName = `alerting-index alerting-index__${activeColumn}`
|
const pageContentsClassName = `alerting-index alerting-index__${activeColumn}`
|
||||||
|
@ -57,7 +42,7 @@ const AlertingIndex: FunctionComponent<StateProps> = ({
|
||||||
<Page titleTag={pageTitleSuffixer(['Alerts'])}>
|
<Page titleTag={pageTitleSuffixer(['Alerts'])}>
|
||||||
<Page.Header fullWidth={true} testID="alerts-page--header">
|
<Page.Header fullWidth={true} testID="alerts-page--header">
|
||||||
<Page.Title title="Alerts" />
|
<Page.Title title="Alerts" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.Contents
|
<Page.Contents
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
@ -66,11 +51,6 @@ const AlertingIndex: FunctionComponent<StateProps> = ({
|
||||||
>
|
>
|
||||||
<GetResources resources={[ResourceType.Labels, ResourceType.Buckets]}>
|
<GetResources resources={[ResourceType.Labels, ResourceType.Buckets]}>
|
||||||
<GetAssetLimits>
|
<GetAssetLimits>
|
||||||
<AssetLimitAlert
|
|
||||||
resourceName={limitedResources}
|
|
||||||
limitStatus={limitStatus}
|
|
||||||
className="load-data--asset-alert"
|
|
||||||
/>
|
|
||||||
<SelectGroup
|
<SelectGroup
|
||||||
className="alerting-index--selector"
|
className="alerting-index--selector"
|
||||||
shape={ButtonShape.StretchToFit}
|
shape={ButtonShape.StretchToFit}
|
||||||
|
@ -152,11 +132,4 @@ const AlertingIndex: FunctionComponent<StateProps> = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstp = ({cloud: {limits}}: AppState) => {
|
export default AlertingIndex
|
||||||
return {
|
|
||||||
limitStatus: extractMonitoringLimitStatus(limits),
|
|
||||||
limitedResources: extractLimitedMonitoringResources(limits),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mstp)(AlertingIndex)
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {FC, ReactChild, useState} from 'react'
|
import React, {FC, ReactChild, useState} from 'react'
|
||||||
|
import {connect} from 'react-redux'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {ResourceType} from 'src/types'
|
import {AppState, ResourceType} from 'src/types'
|
||||||
|
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {
|
import {
|
||||||
|
@ -17,13 +19,17 @@ import {
|
||||||
QuestionMarkTooltip,
|
QuestionMarkTooltip,
|
||||||
ComponentColor,
|
ComponentColor,
|
||||||
} from '@influxdata/clockface'
|
} from '@influxdata/clockface'
|
||||||
|
import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
import {extractMonitoringLimitStatus} from 'src/cloud/utils/limits'
|
||||||
|
|
||||||
type ColumnTypes =
|
type ColumnTypes =
|
||||||
| ResourceType.NotificationRules
|
| ResourceType.NotificationRules
|
||||||
| ResourceType.NotificationEndpoints
|
| ResourceType.NotificationEndpoints
|
||||||
| ResourceType.Checks
|
| ResourceType.Checks
|
||||||
|
|
||||||
interface Props {
|
interface OwnProps {
|
||||||
type: ColumnTypes
|
type: ColumnTypes
|
||||||
title: string
|
title: string
|
||||||
createButton: JSX.Element
|
createButton: JSX.Element
|
||||||
|
@ -31,10 +37,15 @@ interface Props {
|
||||||
children: (searchTerm: string) => ReactChild
|
children: (searchTerm: string) => ReactChild
|
||||||
}
|
}
|
||||||
|
|
||||||
const AlertsColumnHeader: FC<Props> = ({
|
interface StateProps {
|
||||||
|
limitStatus: LimitStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
const AlertsColumnHeader: FC<OwnProps & StateProps> = ({
|
||||||
type,
|
type,
|
||||||
children,
|
children,
|
||||||
title,
|
title,
|
||||||
|
limitStatus,
|
||||||
createButton,
|
createButton,
|
||||||
questionMarkTooltipContents,
|
questionMarkTooltipContents,
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -75,11 +86,20 @@ const AlertsColumnHeader: FC<Props> = ({
|
||||||
autoHide={true}
|
autoHide={true}
|
||||||
style={{width: '100%', height: '100%'}}
|
style={{width: '100%', height: '100%'}}
|
||||||
>
|
>
|
||||||
<div className="alerting-index--list">{children(searchTerm)}</div>
|
<div className="alerting-index--list">
|
||||||
|
{children(searchTerm)}
|
||||||
|
<AssetLimitAlert resourceName={title} limitStatus={limitStatus} />
|
||||||
|
</div>
|
||||||
</DapperScrollbars>
|
</DapperScrollbars>
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AlertsColumnHeader
|
const mstp = ({cloud: {limits}}: AppState) => {
|
||||||
|
return {
|
||||||
|
limitStatus: extractMonitoringLimitStatus(limits),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mstp)(AlertsColumnHeader)
|
||||||
|
|
|
@ -102,11 +102,6 @@ class BucketsTab extends PureComponent<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AssetLimitAlert
|
|
||||||
resourceName="buckets"
|
|
||||||
limitStatus={limitStatus}
|
|
||||||
className="load-data--asset-alert"
|
|
||||||
/>
|
|
||||||
<TabbedPageHeader
|
<TabbedPageHeader
|
||||||
childrenLeft={leftHeaderItems}
|
childrenLeft={leftHeaderItems}
|
||||||
childrenRight={rightHeaderItems}
|
childrenRight={rightHeaderItems}
|
||||||
|
@ -136,6 +131,11 @@ class BucketsTab extends PureComponent<Props, State> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FilterBuckets>
|
</FilterBuckets>
|
||||||
|
<AssetLimitAlert
|
||||||
|
resourceName="buckets"
|
||||||
|
limitStatus={limitStatus}
|
||||||
|
className="load-data--asset-alert"
|
||||||
|
/>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column
|
<Grid.Column
|
||||||
widthXS={Columns.Twelve}
|
widthXS={Columns.Twelve}
|
||||||
|
|
|
@ -11,22 +11,15 @@ import BucketsTab from 'src/buckets/components/BucketsTab'
|
||||||
import GetResources from 'src/resources/components/GetResources'
|
import GetResources from 'src/resources/components/GetResources'
|
||||||
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
||||||
import LimitChecker from 'src/cloud/components/LimitChecker'
|
import LimitChecker from 'src/cloud/components/LimitChecker'
|
||||||
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
|
||||||
import LineProtocolWizard from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard'
|
import LineProtocolWizard from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard'
|
||||||
import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard'
|
import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard'
|
||||||
import UpdateBucketOverlay from 'src/buckets/components/UpdateBucketOverlay'
|
import UpdateBucketOverlay from 'src/buckets/components/UpdateBucketOverlay'
|
||||||
import RenameBucketOverlay from 'src/buckets/components/RenameBucketOverlay'
|
import RenameBucketOverlay from 'src/buckets/components/RenameBucketOverlay'
|
||||||
import CreateScraperOverlay from 'src/scrapers/components/CreateScraperOverlay'
|
import CreateScraperOverlay from 'src/scrapers/components/CreateScraperOverlay'
|
||||||
import DeleteDataOverlay from 'src/shared/components/DeleteDataOverlay'
|
import DeleteDataOverlay from 'src/shared/components/DeleteDataOverlay'
|
||||||
import {
|
import {Page} from '@influxdata/clockface'
|
||||||
FlexBox,
|
|
||||||
FlexDirection,
|
|
||||||
JustifyContent,
|
|
||||||
Page,
|
|
||||||
} from '@influxdata/clockface'
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {extractRateLimitResources} from 'src/cloud/utils/limits'
|
|
||||||
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
||||||
import {getOrg} from 'src/organizations/selectors'
|
import {getOrg} from 'src/organizations/selectors'
|
||||||
|
|
||||||
|
@ -38,7 +31,6 @@ import {AppState, Organization, ResourceType} from 'src/types'
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
org: Organization
|
org: Organization
|
||||||
limitedResources: string[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bucketsPath = `/${ORGS}/${ORG_ID}/load-data/${BUCKETS}/${BUCKET_ID}`
|
const bucketsPath = `/${ORGS}/${ORG_ID}/load-data/${BUCKETS}/${BUCKET_ID}`
|
||||||
|
@ -53,14 +45,6 @@ class BucketsIndex extends Component<StateProps> {
|
||||||
<Page titleTag={pageTitleSuffixer(['Buckets', 'Load Data'])}>
|
<Page titleTag={pageTitleSuffixer(['Buckets', 'Load Data'])}>
|
||||||
<LimitChecker>
|
<LimitChecker>
|
||||||
<LoadDataHeader />
|
<LoadDataHeader />
|
||||||
<FlexBox
|
|
||||||
direction={FlexDirection.Row}
|
|
||||||
justifyContent={JustifyContent.Center}
|
|
||||||
>
|
|
||||||
{this.isCardinalityExceeded && (
|
|
||||||
<RateLimitAlert className="load-data--rate-alert" />
|
|
||||||
)}
|
|
||||||
</FlexBox>
|
|
||||||
<LoadDataTabbedPage activeTab="buckets" orgID={org.id}>
|
<LoadDataTabbedPage activeTab="buckets" orgID={org.id}>
|
||||||
<GetResources
|
<GetResources
|
||||||
resources={[
|
resources={[
|
||||||
|
@ -102,22 +86,12 @@ class BucketsIndex extends Component<StateProps> {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private get isCardinalityExceeded(): boolean {
|
|
||||||
const {limitedResources} = this.props
|
|
||||||
|
|
||||||
return limitedResources.includes('cardinality')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstp = (state: AppState) => {
|
const mstp = (state: AppState) => {
|
||||||
const {
|
|
||||||
cloud: {limits},
|
|
||||||
} = state
|
|
||||||
const org = getOrg(state)
|
const org = getOrg(state)
|
||||||
const limitedResources = extractRateLimitResources(limits)
|
|
||||||
|
|
||||||
return {org, limitedResources}
|
return {org}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect<StateProps, {}, {}>(mstp, null)(BucketsIndex)
|
export default connect<StateProps, {}, {}>(mstp, null)(BucketsIndex)
|
||||||
|
|
|
@ -1,63 +1,61 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {FC} from 'react'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {
|
import {
|
||||||
FlexBox,
|
FlexBox,
|
||||||
FlexDirection,
|
|
||||||
AlignItems,
|
|
||||||
ComponentSize,
|
|
||||||
IconFont,
|
|
||||||
ComponentColor,
|
|
||||||
Alert,
|
|
||||||
JustifyContent,
|
JustifyContent,
|
||||||
|
Gradients,
|
||||||
|
InfluxColors,
|
||||||
|
GradientBox,
|
||||||
|
Panel,
|
||||||
|
Heading,
|
||||||
|
HeadingElement,
|
||||||
|
AlignItems,
|
||||||
} from '@influxdata/clockface'
|
} from '@influxdata/clockface'
|
||||||
|
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {CLOUD} from 'src/shared/constants'
|
import {CLOUD} from 'src/shared/constants'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {LimitStatus} from 'src/cloud/actions/limits'
|
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||||
import CheckoutButton from 'src/cloud/components/CheckoutButton'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
resourceName: string
|
|
||||||
limitStatus: LimitStatus
|
limitStatus: LimitStatus
|
||||||
|
resourceName: string
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AssetLimitAlert extends PureComponent<Props> {
|
const AssetLimitAlert: FC<Props> = ({limitStatus, resourceName, className}) => {
|
||||||
public render() {
|
|
||||||
const {limitStatus, resourceName, className} = this.props
|
|
||||||
|
|
||||||
if (CLOUD && limitStatus === LimitStatus.EXCEEDED) {
|
if (CLOUD && limitStatus === LimitStatus.EXCEEDED) {
|
||||||
return (
|
return (
|
||||||
<FlexBox
|
<GradientBox
|
||||||
direction={FlexDirection.Column}
|
borderGradient={Gradients.MiyazakiSky}
|
||||||
alignItems={AlignItems.Center}
|
borderColor={InfluxColors.Raven}
|
||||||
margin={ComponentSize.Large}
|
|
||||||
stretchToFitWidth={true}
|
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
<Alert icon={IconFont.Cloud} color={ComponentColor.Primary}>
|
<Panel backgroundColor={InfluxColors.Raven} className="asset-alert">
|
||||||
|
<Panel.Header>
|
||||||
|
<Heading element={HeadingElement.H4}>
|
||||||
|
Need more {resourceName}?
|
||||||
|
</Heading>
|
||||||
|
</Panel.Header>
|
||||||
|
<Panel.Body className="asset-alert--contents">
|
||||||
<FlexBox
|
<FlexBox
|
||||||
alignItems={AlignItems.Center}
|
justifyContent={JustifyContent.FlexEnd}
|
||||||
direction={FlexDirection.Row}
|
alignItems={AlignItems.FlexEnd}
|
||||||
justifyContent={JustifyContent.SpaceBetween}
|
stretchToFitHeight={true}
|
||||||
margin={ComponentSize.Medium}
|
|
||||||
>
|
>
|
||||||
<div>
|
<CloudUpgradeButton buttonText={`Get more ${resourceName}`} />
|
||||||
{`Hey there, looks like you have reached the maximum number of
|
|
||||||
${resourceName} you can create as part of your plan.`}
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<CheckoutButton />
|
|
||||||
</FlexBox>
|
|
||||||
</Alert>
|
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
|
</Panel.Body>
|
||||||
|
</Panel>
|
||||||
|
</GradientBox>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default AssetLimitAlert
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import React, {FunctionComponent} from 'react'
|
|
||||||
|
|
||||||
// Components
|
|
||||||
import {FeatureFlag} from 'src/shared/utils/featureFlag'
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
ComponentColor,
|
|
||||||
ComponentSize,
|
|
||||||
FlexBox,
|
|
||||||
FlexDirection,
|
|
||||||
JustifyContent,
|
|
||||||
} from '@influxdata/clockface'
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
import {CLOUD_CHECKOUT_PATH, CLOUD_URL} from 'src/shared/constants'
|
|
||||||
|
|
||||||
const CheckoutButton: FunctionComponent<{}> = () => {
|
|
||||||
const checkoutURL = `${CLOUD_URL}${CLOUD_CHECKOUT_PATH}`
|
|
||||||
const onClick = () => {
|
|
||||||
window.open(checkoutURL, '_self')
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FeatureFlag name="cloudBilling">
|
|
||||||
<FlexBox
|
|
||||||
direction={FlexDirection.Row}
|
|
||||||
justifyContent={JustifyContent.SpaceAround}
|
|
||||||
margin={ComponentSize.Small}
|
|
||||||
>
|
|
||||||
<div>Want to remove these limits?</div>
|
|
||||||
<Button
|
|
||||||
color={ComponentColor.Primary}
|
|
||||||
onClick={onClick}
|
|
||||||
text="Upgrade Now"
|
|
||||||
size={ComponentSize.Small}
|
|
||||||
/>
|
|
||||||
</FlexBox>
|
|
||||||
</FeatureFlag>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CheckoutButton
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {FC} from 'react'
|
||||||
import {connect} from 'react-redux'
|
import {connect} from 'react-redux'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {
|
import {
|
||||||
|
@ -9,10 +10,12 @@ import {
|
||||||
AlignItems,
|
AlignItems,
|
||||||
ComponentSize,
|
ComponentSize,
|
||||||
IconFont,
|
IconFont,
|
||||||
ComponentColor,
|
|
||||||
Alert,
|
|
||||||
JustifyContent,
|
JustifyContent,
|
||||||
|
Gradients,
|
||||||
|
InfluxColors,
|
||||||
|
BannerPanel,
|
||||||
} from '@influxdata/clockface'
|
} from '@influxdata/clockface'
|
||||||
|
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {
|
import {
|
||||||
|
@ -26,7 +29,6 @@ import {CLOUD} from 'src/shared/constants'
|
||||||
// Types
|
// Types
|
||||||
import {AppState} from 'src/types'
|
import {AppState} from 'src/types'
|
||||||
import {LimitStatus} from 'src/cloud/actions/limits'
|
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||||
import CheckoutButton from 'src/cloud/components/CheckoutButton'
|
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
resources: string[]
|
resources: string[]
|
||||||
|
@ -37,65 +39,58 @@ interface OwnProps {
|
||||||
}
|
}
|
||||||
type Props = StateProps & OwnProps
|
type Props = StateProps & OwnProps
|
||||||
|
|
||||||
class RateLimitAlert extends PureComponent<Props> {
|
const RateLimitAlert: FC<Props> = ({status, className, resources}) => {
|
||||||
public render() {
|
const rateLimitAlertClass = classnames('rate-alert', {
|
||||||
const {status, className} = this.props
|
[`${className}`]: className,
|
||||||
|
})
|
||||||
|
|
||||||
if (CLOUD && status === LimitStatus.EXCEEDED) {
|
if (
|
||||||
|
CLOUD &&
|
||||||
|
status === LimitStatus.EXCEEDED &&
|
||||||
|
resources.includes('cardinality')
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<FlexBox
|
<FlexBox
|
||||||
direction={FlexDirection.Column}
|
direction={FlexDirection.Column}
|
||||||
alignItems={AlignItems.Center}
|
alignItems={AlignItems.Center}
|
||||||
margin={ComponentSize.Large}
|
margin={ComponentSize.Large}
|
||||||
stretchToFitWidth={true}
|
className={rateLimitAlertClass}
|
||||||
className={className}
|
|
||||||
>
|
>
|
||||||
<Alert icon={IconFont.Cloud} color={ComponentColor.Primary}>
|
<BannerPanel
|
||||||
|
size={ComponentSize.ExtraSmall}
|
||||||
|
gradient={Gradients.PolarExpress}
|
||||||
|
icon={IconFont.Cloud}
|
||||||
|
hideMobileIcon={true}
|
||||||
|
textColor={InfluxColors.Yeti}
|
||||||
|
>
|
||||||
|
<div className="rate-alert--content">
|
||||||
|
<span>
|
||||||
|
You've reached the maximum{' '}
|
||||||
|
<a
|
||||||
|
href="https://v2.docs.influxdata.com/v2.0/reference/glossary/#series-cardinality"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
series cardinality
|
||||||
|
</a>{' '}
|
||||||
|
available in your plan. Need to write more data?
|
||||||
|
</span>
|
||||||
<FlexBox
|
<FlexBox
|
||||||
alignItems={AlignItems.Center}
|
justifyContent={JustifyContent.Center}
|
||||||
direction={FlexDirection.Row}
|
className="rate-alert--button"
|
||||||
justifyContent={JustifyContent.SpaceBetween}
|
|
||||||
margin={ComponentSize.Medium}
|
|
||||||
>
|
>
|
||||||
<div>
|
<CloudUpgradeButton />
|
||||||
{this.message}
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<CheckoutButton />
|
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
</Alert>
|
</div>
|
||||||
|
</BannerPanel>
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CLOUD) {
|
||||||
|
return <CloudUpgradeButton />
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
|
||||||
|
|
||||||
private get message(): string {
|
|
||||||
return `Hey there, it looks like you have exceeded your plan's ${this.resourceName} limits.${this.additionalMessage}`
|
|
||||||
}
|
|
||||||
|
|
||||||
private get additionalMessage(): string {
|
|
||||||
if (this.props.resources.includes('cardinality')) {
|
|
||||||
return ' Your writes will be rejected until resolved.'
|
|
||||||
}
|
|
||||||
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
private get resourceName(): string {
|
|
||||||
const {resources} = this.props
|
|
||||||
|
|
||||||
const renamedResources = resources.map(resource => {
|
|
||||||
if (resource === 'cardinality') {
|
|
||||||
return 'total series'
|
|
||||||
}
|
|
||||||
|
|
||||||
return resource
|
|
||||||
})
|
|
||||||
|
|
||||||
return renamedResources.join(' and ')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstp = (state: AppState) => {
|
const mstp = (state: AppState) => {
|
||||||
|
|
|
@ -62,7 +62,7 @@ class DashboardPage extends Component<Props> {
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
onManualRefresh={onManualRefresh}
|
onManualRefresh={onManualRefresh}
|
||||||
/>
|
/>
|
||||||
<RateLimitAlert className="dashboard--rate-alert" />
|
<RateLimitAlert />
|
||||||
<VariablesControlBar />
|
<VariablesControlBar />
|
||||||
<DashboardComponent manualRefresh={manualRefresh} />
|
<DashboardComponent manualRefresh={manualRefresh} />
|
||||||
</HoverTimeProvider>
|
</HoverTimeProvider>
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent} from 'react'
|
||||||
|
import {connect} from 'react-redux'
|
||||||
import memoizeOne from 'memoize-one'
|
import memoizeOne from 'memoize-one'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import DashboardCard from 'src/dashboards/components/dashboard_index/DashboardCard'
|
import DashboardCard from 'src/dashboards/components/dashboard_index/DashboardCard'
|
||||||
import {TechnoSpinner} from '@influxdata/clockface'
|
import {TechnoSpinner} from '@influxdata/clockface'
|
||||||
|
import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
|
||||||
|
|
||||||
// Selectors
|
// Selectors
|
||||||
import {getSortedResources, SortTypes} from 'src/shared/utils/sort'
|
import {getSortedResources, SortTypes} from 'src/shared/utils/sort'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {Dashboard, RemoteDataState} from 'src/types'
|
import {AppState, Dashboard, RemoteDataState} from 'src/types'
|
||||||
import {Sort} from 'src/clockface'
|
import {Sort} from 'src/clockface'
|
||||||
|
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||||
|
|
||||||
interface Props {
|
// Utils
|
||||||
|
import {extractDashboardLimits} from 'src/cloud/utils/limits'
|
||||||
|
|
||||||
|
interface StateProps {
|
||||||
|
limitStatus: LimitStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OwnProps {
|
||||||
dashboards: Dashboard[]
|
dashboards: Dashboard[]
|
||||||
sortKey: string
|
sortKey: string
|
||||||
sortDirection: Sort
|
sortDirection: Sort
|
||||||
|
@ -21,7 +31,7 @@ interface Props {
|
||||||
onFilterChange: (searchTerm: string) => void
|
onFilterChange: (searchTerm: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class DashboardCards extends PureComponent<Props> {
|
class DashboardCards extends PureComponent<OwnProps & StateProps> {
|
||||||
private _observer
|
private _observer
|
||||||
private _spinner
|
private _spinner
|
||||||
|
|
||||||
|
@ -110,6 +120,11 @@ export default class DashboardCards extends PureComponent<Props> {
|
||||||
onFilterChange={onFilterChange}
|
onFilterChange={onFilterChange}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<AssetLimitAlert
|
||||||
|
className="dashboards--asset-alert"
|
||||||
|
resourceName="dashboards"
|
||||||
|
limitStatus={this.props.limitStatus}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{windowSize * pages < dashboards.length && (
|
{windowSize * pages < dashboards.length && (
|
||||||
<div
|
<div
|
||||||
|
@ -123,3 +138,15 @@ export default class DashboardCards extends PureComponent<Props> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mstp = (state: AppState) => {
|
||||||
|
const {
|
||||||
|
cloud: {limits},
|
||||||
|
} = state
|
||||||
|
|
||||||
|
return {
|
||||||
|
limitStatus: extractDashboardLimits(limits),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mstp)(DashboardCards)
|
||||||
|
|
|
@ -13,9 +13,8 @@ import {Page} from '@influxdata/clockface'
|
||||||
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 GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
|
||||||
import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
import ResourceSortDropdown from 'src/shared/components/resource_sort_dropdown/ResourceSortDropdown'
|
import ResourceSortDropdown from 'src/shared/components/resource_sort_dropdown/ResourceSortDropdown'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
|
||||||
import DashboardImportOverlay from 'src/dashboards/components/DashboardImportOverlay'
|
import DashboardImportOverlay from 'src/dashboards/components/DashboardImportOverlay'
|
||||||
import CreateFromTemplateOverlay from 'src/templates/components/createFromTemplateOverlay/CreateFromTemplateOverlay'
|
import CreateFromTemplateOverlay from 'src/templates/components/createFromTemplateOverlay/CreateFromTemplateOverlay'
|
||||||
import DashboardExportOverlay from 'src/dashboards/components/DashboardExportOverlay'
|
import DashboardExportOverlay from 'src/dashboards/components/DashboardExportOverlay'
|
||||||
|
@ -53,8 +52,9 @@ class DashboardIndex extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {createDashboard, limitStatus, sortOptions} = this.props
|
const {createDashboard, sortOptions} = this.props
|
||||||
const {searchTerm} = this.state
|
const {searchTerm} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Page
|
<Page
|
||||||
|
@ -63,7 +63,7 @@ class DashboardIndex extends PureComponent<Props, State> {
|
||||||
>
|
>
|
||||||
<Page.Header fullWidth={false}>
|
<Page.Header fullWidth={false}>
|
||||||
<Page.Title title="Dashboards" />
|
<Page.Title title="Dashboards" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.ControlBar fullWidth={false}>
|
<Page.ControlBar fullWidth={false}>
|
||||||
<Page.ControlBarLeft>
|
<Page.ControlBarLeft>
|
||||||
|
@ -97,10 +97,6 @@ class DashboardIndex extends PureComponent<Props, State> {
|
||||||
scrollable={true}
|
scrollable={true}
|
||||||
>
|
>
|
||||||
<GetAssetLimits>
|
<GetAssetLimits>
|
||||||
<AssetLimitAlert
|
|
||||||
resourceName="dashboards"
|
|
||||||
limitStatus={limitStatus}
|
|
||||||
/>
|
|
||||||
<DashboardsIndexContents
|
<DashboardsIndexContents
|
||||||
searchTerm={searchTerm}
|
searchTerm={searchTerm}
|
||||||
onFilterChange={this.handleFilterDashboards}
|
onFilterChange={this.handleFilterDashboards}
|
||||||
|
|
|
@ -79,15 +79,8 @@ class DashboardsIndexContents extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstp = (state: AppState) => {
|
const mstp = (state: AppState) => {
|
||||||
const {
|
|
||||||
cloud: {
|
|
||||||
limits: {status},
|
|
||||||
},
|
|
||||||
} = state
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dashboards: getAll<Dashboard>(state, ResourceType.Dashboards),
|
dashboards: getAll<Dashboard>(state, ResourceType.Dashboards),
|
||||||
limitStatus: status,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {useDispatch} from 'react-redux'
|
||||||
// Components
|
// Components
|
||||||
import TimeMachine from 'src/timeMachine/components/TimeMachine'
|
import TimeMachine from 'src/timeMachine/components/TimeMachine'
|
||||||
import LimitChecker from 'src/cloud/components/LimitChecker'
|
import LimitChecker from 'src/cloud/components/LimitChecker'
|
||||||
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
import {setActiveTimeMachine} from 'src/timeMachine/actions'
|
import {setActiveTimeMachine} from 'src/timeMachine/actions'
|
||||||
|
@ -28,7 +27,6 @@ const DataExplorer: FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LimitChecker>
|
<LimitChecker>
|
||||||
<RateLimitAlert />
|
|
||||||
<div className="data-explorer">
|
<div className="data-explorer">
|
||||||
<HoverTimeProvider>
|
<HoverTimeProvider>
|
||||||
<TimeMachine />
|
<TimeMachine />
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ViewTypeDropdown from 'src/timeMachine/components/view_options/ViewTypeDr
|
||||||
import GetResources from 'src/resources/components/GetResources'
|
import GetResources from 'src/resources/components/GetResources'
|
||||||
import TimeZoneDropdown from 'src/shared/components/TimeZoneDropdown'
|
import TimeZoneDropdown from 'src/shared/components/TimeZoneDropdown'
|
||||||
import DeleteDataButton from 'src/dataExplorer/components/DeleteDataButton'
|
import DeleteDataButton from 'src/dataExplorer/components/DeleteDataButton'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
import SaveAsOverlay from 'src/dataExplorer/components/SaveAsOverlay'
|
import SaveAsOverlay from 'src/dataExplorer/components/SaveAsOverlay'
|
||||||
import DEDeleteDataOverlay from 'src/dataExplorer/components/DeleteDataOverlay'
|
import DEDeleteDataOverlay from 'src/dataExplorer/components/DeleteDataOverlay'
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ const DataExplorerPage: FC = () => {
|
||||||
<GetResources resources={[ResourceType.Variables]}>
|
<GetResources resources={[ResourceType.Variables]}>
|
||||||
<Page.Header fullWidth={true} testID="data-explorer--header">
|
<Page.Header fullWidth={true} testID="data-explorer--header">
|
||||||
<Page.Title title="Data Explorer" />
|
<Page.Title title="Data Explorer" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.ControlBar fullWidth={true}>
|
<Page.ControlBar fullWidth={true}>
|
||||||
<Page.ControlBarLeft>
|
<Page.ControlBarLeft>
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
import Resources from 'src/me/components/Resources'
|
import Resources from 'src/me/components/Resources'
|
||||||
import Docs from 'src/me/components/Docs'
|
import Docs from 'src/me/components/Docs'
|
||||||
import GettingStarted from 'src/me/components/GettingStarted'
|
import GettingStarted from 'src/me/components/GettingStarted'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
||||||
|
@ -39,7 +39,7 @@ export class MePage extends PureComponent<Props> {
|
||||||
<Page titleTag={pageTitleSuffixer(['Home'])}>
|
<Page titleTag={pageTitleSuffixer(['Home'])}>
|
||||||
<Page.Header fullWidth={false}>
|
<Page.Header fullWidth={false}>
|
||||||
<Page.Title title="Getting Started" testID="home-page--header" />
|
<Page.Title title="Getting Started" testID="home-page--header" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.Contents fullWidth={false} scrollable={true}>
|
<Page.Contents fullWidth={false} scrollable={true}>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
import React, {Component} from 'react'
|
import React, {FC} from 'react'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {Page} from '@influxdata/clockface'
|
import {Page} from '@influxdata/clockface'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
|
|
||||||
class LoadDataHeader extends Component {
|
const LoadDataHeader: FC = () => {
|
||||||
public render() {
|
|
||||||
return (
|
return (
|
||||||
<Page.Header fullWidth={false} testID="load-data--header">
|
<Page.Header fullWidth={false} testID="load-data--header">
|
||||||
<Page.Title title="Load Data" />
|
<Page.Title title="Load Data" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert className="load-data--rate-alert" />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LoadDataHeader
|
export default LoadDataHeader
|
||||||
|
|
|
@ -2,14 +2,14 @@ import React, {Component} from 'react'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import {Page} from '@influxdata/clockface'
|
import {Page} from '@influxdata/clockface'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
|
|
||||||
class SettingsHeader extends Component {
|
class SettingsHeader extends Component {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<Page.Header fullWidth={false}>
|
<Page.Header fullWidth={false}>
|
||||||
<Page.Title title="Settings" testID="settings-page--header" />
|
<Page.Title title="Settings" testID="settings-page--header" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,15 @@
|
||||||
import React, {FC} from 'react'
|
import React, {FC} from 'react'
|
||||||
import {connect} from 'react-redux'
|
import {connect} from 'react-redux'
|
||||||
import {get, find} from 'lodash'
|
import {get, find} from 'lodash'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
import {
|
||||||
|
LinkButton,
|
||||||
|
ComponentColor,
|
||||||
|
ComponentSize,
|
||||||
|
ButtonShape,
|
||||||
|
} from '@influxdata/clockface'
|
||||||
import CloudOnly from 'src/shared/components/cloud/CloudOnly'
|
import CloudOnly from 'src/shared/components/cloud/CloudOnly'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
@ -20,17 +27,32 @@ interface StateProps {
|
||||||
inView: boolean
|
inView: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const CloudUpgradeButton: FC<StateProps> = ({inView}) => {
|
interface OwnProps {
|
||||||
|
className?: string
|
||||||
|
buttonText?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const CloudUpgradeButton: FC<StateProps & OwnProps> = ({
|
||||||
|
inView,
|
||||||
|
className,
|
||||||
|
buttonText = 'Upgrade Now',
|
||||||
|
}) => {
|
||||||
|
const cloudUpgradeButtonClass = classnames('upgrade-payg--button', {
|
||||||
|
[`${className}`]: className,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CloudOnly>
|
<CloudOnly>
|
||||||
{inView && (
|
{inView && (
|
||||||
<a
|
<LinkButton
|
||||||
className="cf-button cf-button-sm cf-button-success upgrade-payg--button"
|
className={cloudUpgradeButtonClass}
|
||||||
|
color={ComponentColor.Success}
|
||||||
|
size={ComponentSize.Small}
|
||||||
|
shape={ButtonShape.Default}
|
||||||
href={`${CLOUD_URL}${CLOUD_CHECKOUT_PATH}`}
|
href={`${CLOUD_URL}${CLOUD_CHECKOUT_PATH}`}
|
||||||
target="_self"
|
target="_self"
|
||||||
>
|
text={buttonText}
|
||||||
Upgrade Now
|
/>
|
||||||
</a>
|
|
||||||
)}
|
)}
|
||||||
</CloudOnly>
|
</CloudOnly>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,20 +1,67 @@
|
||||||
.dashboard--rate-alert {
|
|
||||||
padding: 0 $page-gutter;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.load-data--rate-alert {
|
|
||||||
padding: 0 $page-gutter;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
max-width: 1608px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.load-data--asset-alert {
|
.load-data--asset-alert {
|
||||||
padding-bottom: 16px;
|
margin-bottom: $cf-marg-d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might need to remove this eventually
|
.cf-page-control-bar {
|
||||||
.cf-page-header--fixed {
|
+ .rate-alert {
|
||||||
justify-content: space-between;
|
margin: 0 $cf-marg-c $cf-marg-c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rate-alert--content {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.rate-alert--button {
|
||||||
|
margin-top: $cf-marg-b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-page--title {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-alert {
|
||||||
|
height: 100%;
|
||||||
|
background-position: bottom -20px left -20px;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-image: url('../../assets/images/dashboard-empty--dark.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboards--asset-alert {
|
||||||
|
.asset-alert--contents {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.upgrade-payg--button {
|
||||||
|
@include gradient-diag-up($c-pool, $c-rainforest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $cf-nav-menu--breakpoint) {
|
||||||
|
.rate-alert {
|
||||||
|
margin-left: $cf-marg-d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rate-alert--content {
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.rate-alert--button {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-left: $cf-marg-c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-page-control-bar {
|
||||||
|
+ .rate-alert {
|
||||||
|
margin: 0 $cf-marg-d $cf-marg-c;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,6 @@ $nav-size: 50px;
|
||||||
$nav-breakpoint: 800px;
|
$nav-breakpoint: 800px;
|
||||||
$page-header-size: 66px;
|
$page-header-size: 66px;
|
||||||
$page-max-width: 1608px;
|
$page-max-width: 1608px;
|
||||||
$page-gutter: 54px;
|
|
||||||
$page-title-size: 21px;
|
$page-title-size: 21px;
|
||||||
$page-title-weight: 400;
|
$page-title-weight: 400;
|
||||||
$sidebar--width: 50px; //delete this later
|
$sidebar--width: 50px; //delete this later
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
|
import AddResourceDropdown from 'src/shared/components/AddResourceDropdown'
|
||||||
import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
|
import SearchWidget from 'src/shared/components/search_widget/SearchWidget'
|
||||||
import ResourceSortDropdown from 'src/shared/components/resource_sort_dropdown/ResourceSortDropdown'
|
import ResourceSortDropdown from 'src/shared/components/resource_sort_dropdown/ResourceSortDropdown'
|
||||||
import CloudUpgradeButton from 'src/shared/components/CloudUpgradeButton'
|
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {LimitStatus} from 'src/cloud/actions/limits'
|
import {LimitStatus} from 'src/cloud/actions/limits'
|
||||||
|
@ -63,7 +63,7 @@ export default class TasksHeader extends PureComponent<Props> {
|
||||||
<>
|
<>
|
||||||
<Page.Header fullWidth={false} testID="tasks-page--header">
|
<Page.Header fullWidth={false} testID="tasks-page--header">
|
||||||
<Page.Title title="Tasks" />
|
<Page.Title title="Tasks" />
|
||||||
<CloudUpgradeButton />
|
<RateLimitAlert />
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.ControlBar fullWidth={false}>
|
<Page.ControlBar fullWidth={false}>
|
||||||
<Page.ControlBarLeft>
|
<Page.ControlBarLeft>
|
||||||
|
|
|
@ -113,10 +113,6 @@ class TasksPage extends PureComponent<Props, State> {
|
||||||
<Page.Contents fullWidth={false} scrollable={true}>
|
<Page.Contents fullWidth={false} scrollable={true}>
|
||||||
<GetResources resources={[ResourceType.Tasks, ResourceType.Labels]}>
|
<GetResources resources={[ResourceType.Tasks, ResourceType.Labels]}>
|
||||||
<GetAssetLimits>
|
<GetAssetLimits>
|
||||||
<AssetLimitAlert
|
|
||||||
resourceName="tasks"
|
|
||||||
limitStatus={limitStatus}
|
|
||||||
/>
|
|
||||||
<Filter
|
<Filter
|
||||||
list={this.filteredTasks}
|
list={this.filteredTasks}
|
||||||
searchTerm={searchTerm}
|
searchTerm={searchTerm}
|
||||||
|
@ -147,6 +143,10 @@ class TasksPage extends PureComponent<Props, State> {
|
||||||
)}
|
)}
|
||||||
</Filter>
|
</Filter>
|
||||||
{this.hiddenTaskAlert}
|
{this.hiddenTaskAlert}
|
||||||
|
<AssetLimitAlert
|
||||||
|
resourceName="tasks"
|
||||||
|
limitStatus={limitStatus}
|
||||||
|
/>
|
||||||
</GetAssetLimits>
|
</GetAssetLimits>
|
||||||
</GetResources>
|
</GetResources>
|
||||||
</Page.Contents>
|
</Page.Contents>
|
||||||
|
|
|
@ -10,15 +10,9 @@ import LoadDataHeader from 'src/settings/components/LoadDataHeader'
|
||||||
import Collectors from 'src/telegrafs/components/Collectors'
|
import Collectors from 'src/telegrafs/components/Collectors'
|
||||||
import GetResources from 'src/resources/components/GetResources'
|
import GetResources from 'src/resources/components/GetResources'
|
||||||
import LimitChecker from 'src/cloud/components/LimitChecker'
|
import LimitChecker from 'src/cloud/components/LimitChecker'
|
||||||
import RateLimitAlert from 'src/cloud/components/RateLimitAlert'
|
|
||||||
import TelegrafInstructionsOverlay from 'src/telegrafs/components/TelegrafInstructionsOverlay'
|
import TelegrafInstructionsOverlay from 'src/telegrafs/components/TelegrafInstructionsOverlay'
|
||||||
import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard'
|
import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard'
|
||||||
import {
|
import {Page} from '@influxdata/clockface'
|
||||||
FlexBox,
|
|
||||||
FlexDirection,
|
|
||||||
JustifyContent,
|
|
||||||
Page,
|
|
||||||
} from '@influxdata/clockface'
|
|
||||||
import OverlayHandler, {
|
import OverlayHandler, {
|
||||||
RouteOverlay,
|
RouteOverlay,
|
||||||
} from 'src/overlays/components/RouteOverlay'
|
} from 'src/overlays/components/RouteOverlay'
|
||||||
|
@ -39,7 +33,6 @@ const TelegrafOutputOverlay = RouteOverlay(
|
||||||
)
|
)
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {extractRateLimitResources} from 'src/cloud/utils/limits'
|
|
||||||
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
import {pageTitleSuffixer} from 'src/shared/utils/pageTitles'
|
||||||
import {getOrg} from 'src/organizations/selectors'
|
import {getOrg} from 'src/organizations/selectors'
|
||||||
|
|
||||||
|
@ -51,7 +44,6 @@ import {ORGS, ORG_ID, TELEGRAFS} from 'src/shared/constants/routes'
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
org: Organization
|
org: Organization
|
||||||
limitedResources: string[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const telegrafsPath = `/${ORGS}/${ORG_ID}/load-data/${TELEGRAFS}`
|
const telegrafsPath = `/${ORGS}/${ORG_ID}/load-data/${TELEGRAFS}`
|
||||||
|
@ -66,14 +58,6 @@ class TelegrafsPage extends PureComponent<StateProps> {
|
||||||
<Page titleTag={pageTitleSuffixer(['Telegraf', 'Load Data'])}>
|
<Page titleTag={pageTitleSuffixer(['Telegraf', 'Load Data'])}>
|
||||||
<LimitChecker>
|
<LimitChecker>
|
||||||
<LoadDataHeader />
|
<LoadDataHeader />
|
||||||
<FlexBox
|
|
||||||
direction={FlexDirection.Row}
|
|
||||||
justifyContent={JustifyContent.Center}
|
|
||||||
>
|
|
||||||
{this.isCardinalityExceeded && (
|
|
||||||
<RateLimitAlert className="load-data--rate-alert" />
|
|
||||||
)}
|
|
||||||
</FlexBox>
|
|
||||||
<LoadDataTabbedPage activeTab="telegrafs" orgID={org.id}>
|
<LoadDataTabbedPage activeTab="telegrafs" orgID={org.id}>
|
||||||
<GetResources
|
<GetResources
|
||||||
resources={[ResourceType.Buckets, ResourceType.Telegrafs]}
|
resources={[ResourceType.Buckets, ResourceType.Telegrafs]}
|
||||||
|
@ -101,21 +85,11 @@ class TelegrafsPage extends PureComponent<StateProps> {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
private get isCardinalityExceeded(): boolean {
|
|
||||||
const {limitedResources} = this.props
|
|
||||||
|
|
||||||
return limitedResources.includes('cardinality')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstp = (state: AppState) => {
|
const mstp = (state: AppState) => {
|
||||||
const org = getOrg(state)
|
const org = getOrg(state)
|
||||||
const {
|
return {org}
|
||||||
cloud: {limits},
|
|
||||||
} = state
|
|
||||||
const limitedResources = extractRateLimitResources(limits)
|
|
||||||
|
|
||||||
return {org, limitedResources}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect<StateProps>(mstp)(TelegrafsPage)
|
export default connect<StateProps>(mstp)(TelegrafsPage)
|
||||||
|
|
|
@ -747,10 +747,10 @@
|
||||||
debug "^3.1.0"
|
debug "^3.1.0"
|
||||||
lodash.once "^4.1.1"
|
lodash.once "^4.1.1"
|
||||||
|
|
||||||
"@influxdata/clockface@2.2.0":
|
"@influxdata/clockface@2.3.1":
|
||||||
version "2.2.0"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@influxdata/clockface/-/clockface-2.2.0.tgz#73f09f4832d6b6bad53af029844a11dd6562527e"
|
resolved "https://registry.yarnpkg.com/@influxdata/clockface/-/clockface-2.3.1.tgz#562a218e62b50ba16cd4a4e1e88b2e335289c595"
|
||||||
integrity sha512-pIQPJXjvVgzcryhAjgZPSoC5BRLbQb1sIIY9l6KQCg4DWJkxqFC/sPI7qJItRXd8kiPXbfbHvXGAwqIY+TdWNQ==
|
integrity sha512-NqPaCT/vUOCEnjAekfECAvUS3OiSwHREwG/5YuawCw5EoswcUc9h6sMSo2spPxXQuiVAB4RcsxeX3+hqP6pU7w==
|
||||||
|
|
||||||
"@influxdata/flux-lsp-browser@^0.5.11":
|
"@influxdata/flux-lsp-browser@^0.5.11":
|
||||||
version "0.5.11"
|
version "0.5.11"
|
||||||
|
|
Loading…
Reference in New Issue