Display kapacitor name and url in header

pull/4675/head
Andrew Watkins 2018-10-30 13:41:48 -07:00
parent 363883c598
commit 5983ef2dfc
7 changed files with 113 additions and 65 deletions

View File

@ -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'
}`

View File

@ -103,6 +103,7 @@ class KapacitorRulePage extends Component<Props, State> {
if (!query) {
return <div className="page-spinner" />
}
return (
<KapacitorRule
source={source}

View File

@ -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

View File

@ -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
}
}

View File

@ -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,
}

View File

@ -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,

View File

@ -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)