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