Refactor InfluxTable and convert to ts
parent
c78f97972d
commit
149cd4a27f
|
@ -0,0 +1,56 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
import {Source} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
source: Source
|
||||
currentSource: Source
|
||||
}
|
||||
|
||||
class ConnectionLink extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {source} = this.props
|
||||
return (
|
||||
<h5 className="margin-zero">
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={<strong>{source.name}</strong>}
|
||||
>
|
||||
<Link
|
||||
to={`${location.pathname}/${source.id}/edit`}
|
||||
className={this.className}
|
||||
>
|
||||
<strong>{source.name}</strong>
|
||||
{this.default}
|
||||
</Link>
|
||||
</Authorized>
|
||||
</h5>
|
||||
)
|
||||
}
|
||||
|
||||
private get className(): string {
|
||||
if (this.isCurrentSource) {
|
||||
return 'link-success'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
private get default(): string {
|
||||
const {source} = this.props
|
||||
if (source.default) {
|
||||
return ' (Default)'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
private get isCurrentSource(): boolean {
|
||||
const {source, currentSource} = this.props
|
||||
return source.id === currentSource.id
|
||||
}
|
||||
}
|
||||
|
||||
export default ConnectionLink
|
|
@ -1,247 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {Link, withRouter} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
import Dropdown from 'shared/components/Dropdown'
|
||||
import QuestionMarkTooltip from 'shared/components/QuestionMarkTooltip'
|
||||
import ConfirmButton from 'shared/components/ConfirmButton'
|
||||
|
||||
const kapacitorDropdown = (
|
||||
kapacitors,
|
||||
source,
|
||||
router,
|
||||
setActiveKapacitor,
|
||||
handleDeleteKapacitor
|
||||
) => {
|
||||
if (!kapacitors || kapacitors.length === 0) {
|
||||
return (
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<Link
|
||||
to={`/sources/${source.id}/kapacitors/new`}
|
||||
className="btn btn-xs btn-default"
|
||||
>
|
||||
<span className="icon plus" /> Add Kapacitor Connection
|
||||
</Link>
|
||||
</Authorized>
|
||||
)
|
||||
}
|
||||
const kapacitorItems = kapacitors.map(k => {
|
||||
return {
|
||||
text: k.name,
|
||||
resource: `/sources/${source.id}/kapacitors/${k.id}`,
|
||||
kapacitor: k,
|
||||
}
|
||||
})
|
||||
|
||||
const activeKapacitor = kapacitors.find(k => k.active)
|
||||
|
||||
let selected = ''
|
||||
if (activeKapacitor) {
|
||||
selected = activeKapacitor.name
|
||||
} else {
|
||||
selected = kapacitorItems[0].text
|
||||
}
|
||||
|
||||
const unauthorizedDropdown = (
|
||||
<div className="source-table--kapacitor__view-only">{selected}</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={unauthorizedDropdown}
|
||||
>
|
||||
<Dropdown
|
||||
className="dropdown-260"
|
||||
buttonColor="btn-primary"
|
||||
buttonSize="btn-xs"
|
||||
items={kapacitorItems}
|
||||
onChoose={setActiveKapacitor}
|
||||
addNew={{
|
||||
url: `/sources/${source.id}/kapacitors/new`,
|
||||
text: 'Add Kapacitor Connection',
|
||||
}}
|
||||
actions={[
|
||||
{
|
||||
icon: 'pencil',
|
||||
text: 'edit',
|
||||
handler: item => {
|
||||
router.push(`${item.resource}/edit`)
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'trash',
|
||||
text: 'delete',
|
||||
handler: item => {
|
||||
handleDeleteKapacitor(item.kapacitor)
|
||||
},
|
||||
confirmable: true,
|
||||
},
|
||||
]}
|
||||
selected={selected}
|
||||
/>
|
||||
</Authorized>
|
||||
)
|
||||
}
|
||||
|
||||
const InfluxTable = ({
|
||||
source,
|
||||
router,
|
||||
sources,
|
||||
location,
|
||||
setActiveKapacitor,
|
||||
handleDeleteSource,
|
||||
handleDeleteKapacitor,
|
||||
isUsingAuth,
|
||||
me,
|
||||
}) => {
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">
|
||||
{isUsingAuth ? (
|
||||
<span>
|
||||
Connections for <em>{me.currentOrganization.name}</em>
|
||||
</span>
|
||||
) : (
|
||||
<span>Connections</span>
|
||||
)}
|
||||
</h2>
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<Link
|
||||
to={`/sources/${source.id}/manage-sources/new`}
|
||||
className="btn btn-sm btn-primary"
|
||||
>
|
||||
<span className="icon plus" /> Add Connection
|
||||
</Link>
|
||||
</Authorized>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<table className="table v-center margin-bottom-zero table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="source-table--connect-col" />
|
||||
<th>InfluxDB Connection</th>
|
||||
<th className="text-right" />
|
||||
<th>
|
||||
Kapacitor Connection{' '}
|
||||
<QuestionMarkTooltip
|
||||
tipID="kapacitor-node-helper"
|
||||
tipContent={
|
||||
'<p>Kapacitor Connections are<br/>scoped per InfluxDB Connection.<br/>Only one can be active at a time.</p>'
|
||||
}
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sources.map(s => {
|
||||
return (
|
||||
<tr
|
||||
key={s.id}
|
||||
className={s.id === source.id ? 'highlight' : null}
|
||||
>
|
||||
<td>
|
||||
{s.id === source.id ? (
|
||||
<div className="btn btn-success btn-xs source-table--connect">
|
||||
Connected
|
||||
</div>
|
||||
) : (
|
||||
<Link
|
||||
className="btn btn-default btn-xs source-table--connect"
|
||||
to={`/sources/${s.id}/hosts`}
|
||||
>
|
||||
Connect
|
||||
</Link>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<h5 className="margin-zero">
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={
|
||||
<strong>{s.name}</strong>
|
||||
}
|
||||
>
|
||||
<Link
|
||||
to={`${location.pathname}/${s.id}/edit`}
|
||||
className={
|
||||
s.id === source.id ? 'link-success' : null
|
||||
}
|
||||
>
|
||||
<strong>{s.name}</strong>
|
||||
{s.default ? ' (Default)' : null}
|
||||
</Link>
|
||||
</Authorized>
|
||||
</h5>
|
||||
<span>{s.url}</span>
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<ConfirmButton
|
||||
customClass="delete-source table--show-on-row-hover"
|
||||
type="btn-danger"
|
||||
size="btn-xs"
|
||||
text="Delete Connection"
|
||||
confirmAction={handleDeleteSource(s)}
|
||||
/>
|
||||
</Authorized>
|
||||
</td>
|
||||
<td className="source-table--kapacitor">
|
||||
{kapacitorDropdown(
|
||||
s.kapacitors,
|
||||
s,
|
||||
router,
|
||||
setActiveKapacitor,
|
||||
handleDeleteKapacitor
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {array, bool, func, shape, string} = PropTypes
|
||||
|
||||
InfluxTable.propTypes = {
|
||||
handleDeleteSource: func.isRequired,
|
||||
location: shape({
|
||||
pathname: string.isRequired,
|
||||
}).isRequired,
|
||||
router: PropTypes.shape({
|
||||
push: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
source: shape({
|
||||
id: string.isRequired,
|
||||
links: shape({
|
||||
proxy: string.isRequired,
|
||||
self: string.isRequired,
|
||||
}),
|
||||
}),
|
||||
sources: array.isRequired,
|
||||
setActiveKapacitor: func.isRequired,
|
||||
handleDeleteKapacitor: func.isRequired,
|
||||
me: shape({
|
||||
currentOrganization: shape({
|
||||
id: string.isRequired,
|
||||
name: string.isRequired,
|
||||
}),
|
||||
}),
|
||||
isUsingAuth: bool,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({auth: {isUsingAuth, me}}) => ({isUsingAuth, me})
|
||||
|
||||
export default connect(mapStateToProps)(withRouter(InfluxTable))
|
|
@ -0,0 +1,71 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import {SetActiveKapacitor, DeleteKapacitor} from 'src/shared/actions/sources'
|
||||
|
||||
import InfluxTableHead from 'src/sources/components/InfluxTableHead'
|
||||
import InfluxTableHeader from 'src/sources/components/InfluxTableHeader'
|
||||
import InfluxTableRow from 'src/sources/components/InfluxTableRow'
|
||||
|
||||
import {Source, Me} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
me: Me
|
||||
source: Source
|
||||
sources: Source[]
|
||||
isUsingAuth: boolean
|
||||
deleteKapacitor: DeleteKapacitor
|
||||
setActiveKapacitor: SetActiveKapacitor
|
||||
onDeleteSource: (source: Source) => () => void
|
||||
}
|
||||
|
||||
class InfluxTable extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {
|
||||
source,
|
||||
sources,
|
||||
setActiveKapacitor,
|
||||
onDeleteSource,
|
||||
deleteKapacitor,
|
||||
isUsingAuth,
|
||||
me,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel">
|
||||
<InfluxTableHeader
|
||||
me={me}
|
||||
source={source}
|
||||
isUsingAuth={isUsingAuth}
|
||||
/>
|
||||
<div className="panel-body">
|
||||
<table className="table v-center margin-bottom-zero table-highlight">
|
||||
<InfluxTableHead />
|
||||
<tbody>
|
||||
{sources.map(s => {
|
||||
return (
|
||||
<InfluxTableRow
|
||||
key={s.id}
|
||||
source={s}
|
||||
currentSource={source}
|
||||
onDeleteSource={onDeleteSource}
|
||||
deleteKapacitor={deleteKapacitor}
|
||||
setActiveKapacitor={setActiveKapacitor}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({auth: {isUsingAuth, me}}) => ({isUsingAuth, me})
|
||||
|
||||
export default connect(mapStateToProps)(InfluxTable)
|
|
@ -0,0 +1,28 @@
|
|||
import React, {SFC, ReactElement} from 'react'
|
||||
|
||||
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
||||
|
||||
import {KAPACITOR_TOOLTIP_COPY} from 'src/sources/constants'
|
||||
|
||||
const InfluxTableHead: SFC<{}> = (): ReactElement<
|
||||
HTMLTableHeaderCellElement
|
||||
> => {
|
||||
return (
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="source-table--connect-col" />
|
||||
<th>InfluxDB Connection</th>
|
||||
<th className="text-right" />
|
||||
<th>
|
||||
Kapacitor Connection
|
||||
<QuestionMarkTooltip
|
||||
tipID="kapacitor-node-helper"
|
||||
tipContent={KAPACITOR_TOOLTIP_COPY}
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
)
|
||||
}
|
||||
|
||||
export default InfluxTableHead
|
|
@ -0,0 +1,47 @@
|
|||
import React, {PureComponent, ReactElement} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
|
||||
import {Me, Source} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
me: Me
|
||||
source: Source
|
||||
isUsingAuth: boolean
|
||||
}
|
||||
|
||||
class InfluxTableHeader extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {source} = this.props
|
||||
|
||||
return (
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">{this.title}</h2>
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<Link
|
||||
to={`/sources/${source.id}/manage-sources/new`}
|
||||
className="btn btn-sm btn-primary"
|
||||
>
|
||||
<span className="icon plus" /> Add Connection
|
||||
</Link>
|
||||
</Authorized>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get title(): ReactElement<HTMLSpanElement> {
|
||||
const {isUsingAuth, me} = this.props
|
||||
if (isUsingAuth) {
|
||||
return (
|
||||
<span>
|
||||
Connections for <em>{me.currentOrganization.name}</em>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
return <span>Connections</span>
|
||||
}
|
||||
}
|
||||
|
||||
export default InfluxTableHeader
|
|
@ -0,0 +1,98 @@
|
|||
import React, {PureComponent, ReactElement} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
|
||||
import * as actions from 'src/shared/actions/sources'
|
||||
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
import ConfirmButton from 'src/shared/components/ConfirmButton'
|
||||
import KapacitorDropdown from 'src/sources/components/KapacitorDropdown'
|
||||
import ConnectionLink from 'src/sources/components/ConnectionLink'
|
||||
|
||||
import {Source} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
source: Source
|
||||
currentSource: Source
|
||||
onDeleteSource: (source: Source) => void
|
||||
setActiveKapacitor: actions.SetActiveKapacitor
|
||||
deleteKapacitor: actions.DeleteKapacitor
|
||||
}
|
||||
|
||||
class InfluxTableRow extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {
|
||||
source,
|
||||
currentSource,
|
||||
setActiveKapacitor,
|
||||
deleteKapacitor,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<tr className={this.className}>
|
||||
<td>{this.connectButton}</td>
|
||||
<td>
|
||||
<ConnectionLink source={source} currentSource={currentSource} />
|
||||
<span>{source.url}</span>
|
||||
</td>
|
||||
<td className="text-right">
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<ConfirmButton
|
||||
type="btn-danger"
|
||||
size="btn-xs"
|
||||
text="Delete Connection"
|
||||
confirmAction={this.handleDeleteSource}
|
||||
customClass="delete-source table--show-on-row-hover"
|
||||
/>
|
||||
</Authorized>
|
||||
</td>
|
||||
<td className="source-table--kapacitor">
|
||||
<KapacitorDropdown
|
||||
source={source}
|
||||
kapacitors={source.kapacitors}
|
||||
deleteKapacitor={deleteKapacitor}
|
||||
setActiveKapacitor={setActiveKapacitor}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
private handleDeleteSource = (): void => {
|
||||
this.props.onDeleteSource(this.props.source)
|
||||
}
|
||||
|
||||
private get connectButton(): ReactElement<HTMLDivElement> {
|
||||
const {source} = this.props
|
||||
if (this.isCurrentSource) {
|
||||
return (
|
||||
<div className="btn btn-success btn-xs source-table--connect">
|
||||
Connected
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
className="btn btn-default btn-xs source-table--connect"
|
||||
to={`/sources/${source.id}/hosts`}
|
||||
>
|
||||
Connect
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
private get className(): string {
|
||||
if (this.isCurrentSource) {
|
||||
return 'hightlight'
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
private get isCurrentSource(): boolean {
|
||||
const {source, currentSource} = this.props
|
||||
return source.id === currentSource.id
|
||||
}
|
||||
}
|
||||
|
||||
export default InfluxTableRow
|
|
@ -0,0 +1,118 @@
|
|||
import React, {PureComponent, ReactElement} from 'react'
|
||||
import {Link, withRouter, RouteComponentProps} from 'react-router'
|
||||
|
||||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||
import {Source, Kapacitor} from 'src/types'
|
||||
import {SetActiveKapacitor} from 'src/shared/actions/sources'
|
||||
|
||||
interface Props {
|
||||
source: Source
|
||||
kapacitors: Kapacitor[]
|
||||
setActiveKapacitor: SetActiveKapacitor
|
||||
deleteKapacitor: (Kapacitor: Kapacitor) => void
|
||||
}
|
||||
|
||||
interface KapacitorItem {
|
||||
text: string
|
||||
resource: string
|
||||
kapacitor: Kapacitor
|
||||
}
|
||||
|
||||
class KapacitorDropdown extends PureComponent<
|
||||
Props & RouteComponentProps<any, any>
|
||||
> {
|
||||
public render() {
|
||||
const {source, router, setActiveKapacitor, deleteKapacitor} = this.props
|
||||
|
||||
if (this.isKapacitorsEmpty) {
|
||||
return (
|
||||
<Authorized requiredRole={EDITOR_ROLE}>
|
||||
<Link
|
||||
to={`/sources/${source.id}/kapacitors/new`}
|
||||
className="btn btn-xs btn-default"
|
||||
>
|
||||
<span className="icon plus" /> Add Kapacitor Connection
|
||||
</Link>
|
||||
</Authorized>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
requiredRole={EDITOR_ROLE}
|
||||
replaceWithIfNotAuthorized={this.UnauthorizedDropdown}
|
||||
>
|
||||
<Dropdown
|
||||
className="dropdown-260"
|
||||
buttonColor="btn-primary"
|
||||
buttonSize="btn-xs"
|
||||
items={this.kapacitorItems}
|
||||
onChoose={setActiveKapacitor}
|
||||
addNew={{
|
||||
url: `/sources/${source.id}/kapacitors/new`,
|
||||
text: 'Add Kapacitor Connection',
|
||||
}}
|
||||
actions={[
|
||||
{
|
||||
icon: 'pencil',
|
||||
text: 'edit',
|
||||
handler: item => {
|
||||
router.push(`${item.resource}/edit`)
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'trash',
|
||||
text: 'delete',
|
||||
handler: item => {
|
||||
deleteKapacitor(item.kapacitor)
|
||||
},
|
||||
confirmable: true,
|
||||
},
|
||||
]}
|
||||
selected={this.selected}
|
||||
/>
|
||||
</Authorized>
|
||||
)
|
||||
}
|
||||
|
||||
private get UnauthorizedDropdown(): ReactElement<HTMLDivElement> {
|
||||
return (
|
||||
<div className="source-table--kapacitor__view-only">{this.selected}</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get isKapacitorsEmpty(): boolean {
|
||||
const {kapacitors} = this.props
|
||||
return !kapacitors || kapacitors.length === 0
|
||||
}
|
||||
|
||||
private get kapacitorItems(): KapacitorItem[] {
|
||||
const {kapacitors, source} = this.props
|
||||
|
||||
return kapacitors.map(k => {
|
||||
return {
|
||||
text: k.name,
|
||||
resource: `/sources/${source.id}/kapacitors/${k.id}`,
|
||||
kapacitor: k,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private get activeKapacitor(): Kapacitor {
|
||||
return this.props.kapacitors.find(k => k.active)
|
||||
}
|
||||
|
||||
private get selected(): string {
|
||||
let selected = ''
|
||||
if (this.activeKapacitor) {
|
||||
selected = this.activeKapacitor.name
|
||||
} else {
|
||||
selected = this.kapacitorItems[0].text
|
||||
}
|
||||
|
||||
return selected
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter<Props>(KapacitorDropdown)
|
|
@ -1,2 +0,0 @@
|
|||
export const REQUIRED_ROLE_COPY =
|
||||
'The minimum Role a user must have<br />in order to access this source.'
|
|
@ -0,0 +1,5 @@
|
|||
export const REQUIRED_ROLE_COPY =
|
||||
'The minimum Role a user must have<br />in order to access this source.'
|
||||
|
||||
export const KAPACITOR_TOOLTIP_COPY =
|
||||
'<p>Kapacitor Connections are<br/>scoped per InfluxDB Connection.<br/>Only one can be active at a time.</p>'
|
|
@ -65,8 +65,8 @@ class ManageSources extends PureComponent<Props> {
|
|||
<InfluxTable
|
||||
source={source}
|
||||
sources={sources}
|
||||
handleDeleteKapacitor={deleteKapacitor}
|
||||
handleDeleteSource={this.handleDeleteSource}
|
||||
deleteKapacitor={deleteKapacitor}
|
||||
onDeleteSource={this.handleDeleteSource}
|
||||
setActiveKapacitor={this.handleSetActiveKapacitor}
|
||||
/>
|
||||
<p className="version-number">Chronograf Version: {VERSION}</p>
|
||||
|
|
Loading…
Reference in New Issue