Display kapacitor name and url in header
parent
363883c598
commit
5983ef2dfc
|
@ -1,17 +1,15 @@
|
||||||
import React, {SFC} from 'react'
|
import React, {SFC} from 'react'
|
||||||
import {Link} from 'react-router'
|
import {Link} from 'react-router'
|
||||||
|
|
||||||
import NoKapacitorError from 'src/shared/components/NoKapacitorError'
|
|
||||||
import KapacitorRulesTable from 'src/kapacitor/components/KapacitorRulesTable'
|
import KapacitorRulesTable from 'src/kapacitor/components/KapacitorRulesTable'
|
||||||
import TasksTable from 'src/kapacitor/components/TasksTable'
|
import TasksTable from 'src/kapacitor/components/TasksTable'
|
||||||
|
|
||||||
import {Source, AlertRule} from 'src/types'
|
import {Source, AlertRule, Kapacitor} from 'src/types'
|
||||||
|
|
||||||
interface KapacitorRulesProps {
|
interface KapacitorRulesProps {
|
||||||
source: Source
|
source: Source
|
||||||
rules: AlertRule[]
|
rules: AlertRule[]
|
||||||
hasKapacitor: boolean
|
kapacitor: Kapacitor
|
||||||
loading: boolean
|
|
||||||
onDelete: (rule: AlertRule) => void
|
onDelete: (rule: AlertRule) => void
|
||||||
onChangeRuleStatus: (rule: AlertRule) => void
|
onChangeRuleStatus: (rule: AlertRule) => void
|
||||||
}
|
}
|
||||||
|
@ -19,35 +17,10 @@ interface KapacitorRulesProps {
|
||||||
const KapacitorRules: SFC<KapacitorRulesProps> = ({
|
const KapacitorRules: SFC<KapacitorRulesProps> = ({
|
||||||
source,
|
source,
|
||||||
rules,
|
rules,
|
||||||
hasKapacitor,
|
|
||||||
loading,
|
|
||||||
onDelete,
|
onDelete,
|
||||||
onChangeRuleStatus,
|
onChangeRuleStatus,
|
||||||
}) => {
|
}) => {
|
||||||
if (loading || !hasKapacitor) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="panel-heading">
|
|
||||||
<h2 className="panel-title">Alert Rules</h2>
|
|
||||||
<button className="btn btn-primary btn-sm disabled" disabled={true}>
|
|
||||||
Create Rule
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="panel-body">
|
|
||||||
<div className="generic-empty-state">
|
|
||||||
{!hasKapacitor ? (
|
|
||||||
<NoKapacitorError source={source} />
|
|
||||||
) : (
|
|
||||||
<p>Loading Rules...</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const builderRules = rules.filter((r: AlertRule) => r.query)
|
const builderRules = rules.filter((r: AlertRule) => r.query)
|
||||||
|
|
||||||
const builderHeader = `${builderRules.length} Alert Rule${
|
const builderHeader = `${builderRules.length} Alert Rule${
|
||||||
builderRules.length === 1 ? '' : 's'
|
builderRules.length === 1 ? '' : 's'
|
||||||
}`
|
}`
|
||||||
|
|
|
@ -103,6 +103,7 @@ class KapacitorRulePage extends Component<Props, State> {
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return <div className="page-spinner" />
|
return <div className="page-spinner" />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KapacitorRule
|
<KapacitorRule
|
||||||
source={source}
|
source={source}
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent} from 'react'
|
||||||
|
|
||||||
import {connect} from 'react-redux'
|
import {connect} from 'react-redux'
|
||||||
import {bindActionCreators} from 'redux'
|
import {bindActionCreators} from 'redux'
|
||||||
|
|
||||||
|
// APIs
|
||||||
import {getActiveKapacitor} from 'src/shared/apis'
|
import {getActiveKapacitor} from 'src/shared/apis'
|
||||||
|
|
||||||
|
// Actions
|
||||||
import * as kapacitorActionCreators from '../actions/view'
|
import * as kapacitorActionCreators from '../actions/view'
|
||||||
|
|
||||||
|
// Components
|
||||||
import KapacitorRules from 'src/kapacitor/components/KapacitorRules'
|
import KapacitorRules from 'src/kapacitor/components/KapacitorRules'
|
||||||
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
||||||
import {Page} from 'src/reusable_ui'
|
import {Page, Spinner} from 'src/reusable_ui'
|
||||||
|
|
||||||
import {Source, Kapacitor, AlertRule} from 'src/types'
|
// Types
|
||||||
|
import {Source, Kapacitor, AlertRule, RemoteDataState} from 'src/types'
|
||||||
|
|
||||||
|
// Decorators
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
import NoKapacitorError from 'src/shared/components/NoKapacitorError'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
source: Source
|
source: Source
|
||||||
|
@ -25,8 +33,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
hasKapacitor: boolean
|
kapacitor: Kapacitor
|
||||||
loading: boolean
|
loading: RemoteDataState
|
||||||
}
|
}
|
||||||
|
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
|
@ -34,30 +42,30 @@ export class KapacitorRulesPage extends PureComponent<Props, State> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
hasKapacitor: false,
|
kapacitor: null,
|
||||||
loading: true,
|
loading: RemoteDataState.NotStarted,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidMount() {
|
public async componentDidMount() {
|
||||||
const {source, actions} = this.props
|
const {source, actions} = this.props
|
||||||
|
this.setState({loading: RemoteDataState.Loading})
|
||||||
const kapacitor: Kapacitor = await getActiveKapacitor(source)
|
const kapacitor: Kapacitor = await getActiveKapacitor(source)
|
||||||
|
|
||||||
if (!kapacitor) {
|
if (!kapacitor) {
|
||||||
return
|
return this.setState({loading: RemoteDataState.Done, kapacitor: null})
|
||||||
}
|
}
|
||||||
|
|
||||||
await actions.fetchRules(kapacitor)
|
await actions.fetchRules(kapacitor)
|
||||||
this.setState({loading: false, hasKapacitor: !!kapacitor})
|
this.setState({loading: RemoteDataState.Done, kapacitor})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {source, rules} = this.props
|
|
||||||
const {hasKapacitor, loading} = this.state
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page className={this.className}>
|
||||||
<Page.Header>
|
<Page.Header>
|
||||||
<Page.Header.Left>
|
<Page.Header.Left>
|
||||||
<Page.Title title="Manage Tasks" />
|
<Page.Title title={this.headerTitle} />
|
||||||
</Page.Header.Left>
|
</Page.Header.Left>
|
||||||
<Page.Header.Right showSourceIndicator={true}>
|
<Page.Header.Right showSourceIndicator={true}>
|
||||||
<QuestionMarkTooltip
|
<QuestionMarkTooltip
|
||||||
|
@ -67,19 +75,51 @@ export class KapacitorRulesPage extends PureComponent<Props, State> {
|
||||||
</Page.Header.Right>
|
</Page.Header.Right>
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.Contents>
|
<Page.Contents>
|
||||||
<KapacitorRules
|
<Spinner loading={this.state.loading}>{this.rules}</Spinner>
|
||||||
source={source}
|
|
||||||
rules={rules}
|
|
||||||
hasKapacitor={hasKapacitor}
|
|
||||||
loading={loading}
|
|
||||||
onDelete={this.handleDeleteRule}
|
|
||||||
onChangeRuleStatus={this.handleRuleStatus}
|
|
||||||
/>
|
|
||||||
</Page.Contents>
|
</Page.Contents>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get rules(): JSX.Element {
|
||||||
|
const {kapacitor} = this.state
|
||||||
|
const {source, rules} = this.props
|
||||||
|
|
||||||
|
if (!kapacitor) {
|
||||||
|
return <NoKapacitorError source={source} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<KapacitorRules
|
||||||
|
rules={rules}
|
||||||
|
source={source}
|
||||||
|
kapacitor={kapacitor}
|
||||||
|
onDelete={this.handleDeleteRule}
|
||||||
|
onChangeRuleStatus={this.handleRuleStatus}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get headerTitle(): string {
|
||||||
|
const {kapacitor} = this.state
|
||||||
|
|
||||||
|
if (!kapacitor) {
|
||||||
|
return 'Manage Tasks'
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Manage Tasks on "${kapacitor.name}" @ ${kapacitor.url}`
|
||||||
|
}
|
||||||
|
|
||||||
|
private get className(): string {
|
||||||
|
const {kapacitor} = this.state
|
||||||
|
|
||||||
|
if (!kapacitor) {
|
||||||
|
return 'empty-tasks-page'
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
private handleDeleteRule = (rule: AlertRule) => {
|
private handleDeleteRule = (rule: AlertRule) => {
|
||||||
const {actions} = this.props
|
const {actions} = this.props
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Libraries
|
||||||
|
import React, {Component} from 'react'
|
||||||
|
|
||||||
|
// Types
|
||||||
|
import {RemoteDataState} from 'src/types'
|
||||||
|
|
||||||
|
// Decorators
|
||||||
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
loading: RemoteDataState
|
||||||
|
children: JSX.Element[] | JSX.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
@ErrorHandling
|
||||||
|
export default class Spinner extends Component<Props> {
|
||||||
|
public render() {
|
||||||
|
return this.children
|
||||||
|
}
|
||||||
|
|
||||||
|
private get children(): JSX.Element | JSX.Element[] {
|
||||||
|
const {loading, children} = this.props
|
||||||
|
|
||||||
|
if (
|
||||||
|
loading === RemoteDataState.Loading ||
|
||||||
|
loading === RemoteDataState.NotStarted
|
||||||
|
) {
|
||||||
|
return <div className="spinner" />
|
||||||
|
}
|
||||||
|
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import Page from './components/page_layout/Page'
|
||||||
import Panel, {PanelType} from './components/panel/Panel'
|
import Panel, {PanelType} from './components/panel/Panel'
|
||||||
import Radio from './components/radio_buttons/RadioButtons'
|
import Radio from './components/radio_buttons/RadioButtons'
|
||||||
import SlideToggle from './components/slide_toggle/SlideToggle'
|
import SlideToggle from './components/slide_toggle/SlideToggle'
|
||||||
|
import Spinner from './components/spinners/Spinner'
|
||||||
|
|
||||||
// Import Types
|
// Import Types
|
||||||
import {
|
import {
|
||||||
|
@ -53,4 +54,5 @@ export {
|
||||||
Greys,
|
Greys,
|
||||||
IconFont,
|
IconFont,
|
||||||
Columns,
|
Columns,
|
||||||
|
Spinner,
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,7 @@
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
*/
|
*/
|
||||||
.sortable-header {
|
.sortable-header {
|
||||||
transition:
|
transition: color 0.25s ease, background-color 0.25s ease;
|
||||||
color 0.25s ease,
|
|
||||||
background-color 0.25s ease;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
|
@ -64,10 +62,7 @@
|
||||||
color: $g20-white;
|
color: $g20-white;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
transition:
|
transition: opacity 0.25s ease, color 0.25s ease, transform 0.35s ease;
|
||||||
opacity 0.25s ease,
|
|
||||||
color 0.25s ease,
|
|
||||||
transform 0.35s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -80,7 +75,9 @@
|
||||||
background-color: $g5-pepper;
|
background-color: $g5-pepper;
|
||||||
color: $g19-ghost;
|
color: $g19-ghost;
|
||||||
|
|
||||||
> .icon {opacity: 1;}
|
> .icon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.sorting-ascending > .icon {
|
&.sorting-ascending > .icon {
|
||||||
transform: translateY(-50%) rotate(180deg);
|
transform: translateY(-50%) rotate(180deg);
|
||||||
|
@ -140,9 +137,7 @@ $table-tab-scrollbar-height: 6px;
|
||||||
background-color: $g4-onyx;
|
background-color: $g4-onyx;
|
||||||
color: $g11-sidewalk;
|
color: $g11-sidewalk;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
transition:
|
transition: color 0.25s ease, background-color 0.25s ease;
|
||||||
color 0.25s ease,
|
|
||||||
background-color 0.25s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $g5-pepper;
|
background-color: $g5-pepper;
|
||||||
|
@ -169,7 +164,6 @@ $table-tab-scrollbar-height: 6px;
|
||||||
border-radius: 0 $radius-small $radius-small $radius-small;
|
border-radius: 0 $radius-small $radius-small $radius-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.table > tbody > tr.highlight,
|
.table > tbody > tr.highlight,
|
||||||
.table.table-highlight > tbody > tr.highlight {
|
.table.table-highlight > tbody > tr.highlight {
|
||||||
background-color: $g4-onyx;
|
background-color: $g4-onyx;
|
||||||
|
@ -180,6 +174,7 @@ $table-tab-scrollbar-height: 6px;
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
*/
|
*/
|
||||||
.alert-history-page,
|
.alert-history-page,
|
||||||
|
.empty-tasks-page,
|
||||||
.hosts-list-page {
|
.hosts-list-page {
|
||||||
.container-fluid,
|
.container-fluid,
|
||||||
.row,
|
.row,
|
||||||
|
|
|
@ -8,13 +8,13 @@ import NoKapacitorError from 'src/shared/components/NoKapacitorError'
|
||||||
import KapacitorRulesTable from 'src/kapacitor/components/KapacitorRulesTable'
|
import KapacitorRulesTable from 'src/kapacitor/components/KapacitorRulesTable'
|
||||||
import TasksTable from 'src/kapacitor/components/TasksTable'
|
import TasksTable from 'src/kapacitor/components/TasksTable'
|
||||||
|
|
||||||
import {source, kapacitorRules} from 'test/resources'
|
import {source, kapacitorRules, kapacitor} from 'test/resources'
|
||||||
|
|
||||||
describe('Kapacitor.Containers.KapacitorRules', () => {
|
describe('Kapacitor.Containers.KapacitorRules', () => {
|
||||||
const props = {
|
const props = {
|
||||||
source,
|
source,
|
||||||
rules: kapacitorRules,
|
rules: kapacitorRules,
|
||||||
hasKapacitor: true,
|
kapacitor,
|
||||||
loading: false,
|
loading: false,
|
||||||
onDelete: () => {},
|
onDelete: () => {},
|
||||||
onChangeRuleStatus: () => {},
|
onChangeRuleStatus: () => {},
|
||||||
|
@ -52,7 +52,11 @@ describe('Kapacitor.Containers.KapacitorRules', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders NoKapacitorError if not loading and no kapacitor configured', () => {
|
it('renders NoKapacitorError if not loading and no kapacitor configured', () => {
|
||||||
const noKapacitorProps = {...props, loading: false, hasKapacitor: false}
|
const noKapacitorProps = {
|
||||||
|
...props,
|
||||||
|
loading: false,
|
||||||
|
hasKapacitor: false,
|
||||||
|
}
|
||||||
const wrapper = shallow(<KapacitorRules {...noKapacitorProps} />)
|
const wrapper = shallow(<KapacitorRules {...noKapacitorProps} />)
|
||||||
const noKapacitorError = wrapper.find(NoKapacitorError)
|
const noKapacitorError = wrapper.find(NoKapacitorError)
|
||||||
expect(noKapacitorError.length).toEqual(1)
|
expect(noKapacitorError.length).toEqual(1)
|
||||||
|
|
Loading…
Reference in New Issue