diff --git a/ui/src/dataLoaders/actions/dataLoaders.ts b/ui/src/dataLoaders/actions/dataLoaders.ts index f935fb0ed2..27982a264e 100644 --- a/ui/src/dataLoaders/actions/dataLoaders.ts +++ b/ui/src/dataLoaders/actions/dataLoaders.ts @@ -38,8 +38,13 @@ import { Permission, } from '@influxdata/influx' import {Dispatch} from 'redux' -import {addTelegraf} from 'src/telegrafs/actions' +import {addTelegraf, editTelegraf} from 'src/telegrafs/actions' import {addAuthorization} from 'src/authorizations/actions' +import {notify} from 'src/shared/actions/notifications' +import { + TelegrafConfigCreationError, + TelegrafConfigCreationSuccess, +} from 'src/shared/copy/notifications' type GetState = () => AppState @@ -365,11 +370,12 @@ export const createOrUpdateTelegrafConfigAsync = () => async ( ) if (telegrafConfigID) { - await client.telegrafConfigs.update(telegrafConfigID, { + const telegraf = await client.telegrafConfigs.update(telegrafConfigID, { name: telegrafConfigName, description: telegrafConfigDescription, plugins, }) + dispatch(editTelegraf(telegraf)) dispatch(setTelegrafConfigID(telegrafConfigID)) return } @@ -378,78 +384,87 @@ export const createOrUpdateTelegrafConfigAsync = () => async ( } const createTelegraf = async (dispatch, getState, plugins) => { - const { - dataLoading: { - dataLoaders: {telegrafConfigName, telegrafConfigDescription}, - steps: {bucket, orgID, bucketID}, - }, - } = getState() - - const telegrafRequest: TelegrafRequest = { - name: telegrafConfigName, - description: telegrafConfigDescription, - agent: {collectionInterval: DEFAULT_COLLECTION_INTERVAL}, - organizationID: orgID, - plugins, - } - - // create telegraf config - const tc = await client.telegrafConfigs.create(telegrafRequest) - - const permissions = [ - { - action: Permission.ActionEnum.Write, - resource: { - type: PermissionResource.TypeEnum.Buckets, - id: bucketID, - orgID, + try { + const { + dataLoading: { + dataLoaders: {telegrafConfigName, telegrafConfigDescription}, + steps: {bucket, orgID, bucketID}, }, - }, - { - action: Permission.ActionEnum.Read, - resource: {type: PermissionResource.TypeEnum.Telegrafs, id: tc.id, orgID}, - }, - ] + } = getState() - const token = { - name: `${telegrafConfigName} token`, - orgID, - description: `WRITE ${bucket} bucket / READ ${telegrafConfigName} telegraf config`, - permissions, + const telegrafRequest: TelegrafRequest = { + name: telegrafConfigName, + description: telegrafConfigDescription, + agent: {collectionInterval: DEFAULT_COLLECTION_INTERVAL}, + organizationID: orgID, + plugins, + } + + // create telegraf config + const tc = await client.telegrafConfigs.create(telegrafRequest) + + const permissions = [ + { + action: Permission.ActionEnum.Write, + resource: { + type: PermissionResource.TypeEnum.Buckets, + id: bucketID, + orgID, + }, + }, + { + action: Permission.ActionEnum.Read, + resource: { + type: PermissionResource.TypeEnum.Telegrafs, + id: tc.id, + orgID, + }, + }, + ] + + const token = { + name: `${telegrafConfigName} token`, + orgID, + description: `WRITE ${bucket} bucket / READ ${telegrafConfigName} telegraf config`, + permissions, + } + + // create token + const createdToken = await createAuthorization(token) + + // add token to data loader state + dispatch(setToken(createdToken.token)) + + // add token to authorizations state + dispatch(addAuthorization(createdToken)) + + // create token label + const properties = { + color: '#FFFFFF', + description: `token for telegraf config: ${telegrafConfigName}`, + tokenID: createdToken.id, + } as ILabelProperties // hack to make compiler work + + const createdLabel = await client.labels.create({ + orgID, + name: '@influxdata.token', + properties, + }) + + // add label to telegraf config + const label = await client.telegrafConfigs.addLabel(tc.id, createdLabel) + + const config = { + ...tc, + labels: [label], + } + + dispatch(setTelegrafConfigID(tc.id)) + dispatch(addTelegraf(config)) + dispatch(notify(TelegrafConfigCreationSuccess)) + } catch (error) { + dispatch(notify(TelegrafConfigCreationError)) } - - // create token - const createdToken = await createAuthorization(token) - - // add token to data loader state - dispatch(setToken(createdToken.token)) - - // add token to authorizations state - dispatch(addAuthorization(createdToken)) - - // create label - const tokenLabel = { - color: '#FFFFFF', - description: `token for telegraf config: ${telegrafConfigName}`, - tokenID: createdToken.id, - } as ILabelProperties // hack to make compiler work - - const createdLabel = await client.labels.create({ - orgID, - name: '@influxdata.token', - properties: tokenLabel, - }) - - // add label to telegraf config - const label = await client.telegrafConfigs.addLabel(tc.id, createdLabel) - - const config = { - ...tc, - labels: [label], - } - - dispatch(setTelegrafConfigID(tc.id)) - dispatch(addTelegraf(config)) } interface SetActiveTelegrafPlugin { diff --git a/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx index ce21288217..a325fd8a37 100644 --- a/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx @@ -26,7 +26,6 @@ import {notify as notifyAction} from 'src/shared/actions/notifications' // Constants import { - TelegrafConfigCreationSuccess, TelegrafDashboardCreated, TelegrafDashboardFailed, } from 'src/shared/copy/notifications' @@ -127,12 +126,10 @@ export class TelegrafPluginInstructions extends PureComponent { } private handleFormSubmit = async () => { - const {onSaveTelegrafConfig, telegrafConfigID, notify} = this.props + const {onSaveTelegrafConfig, telegrafConfigID} = this.props await onSaveTelegrafConfig() - notify(TelegrafConfigCreationSuccess) - if (!telegrafConfigID) { this.handleCreateDashboardsForPlugins() } diff --git a/ui/src/organizations/components/CollectorRow.tsx b/ui/src/organizations/components/CollectorRow.tsx index 772e4fe3ff..9678838fa5 100644 --- a/ui/src/organizations/components/CollectorRow.tsx +++ b/ui/src/organizations/components/CollectorRow.tsx @@ -1,5 +1,6 @@ // Libraries import React, {PureComponent} from 'react' +import {connect} from 'react-redux' // Components import { @@ -21,7 +22,11 @@ import EditableDescription from 'src/shared/components/editable_description/Edit // Constants import {DEFAULT_COLLECTOR_NAME} from 'src/dashboards/constants' -interface Props { +// Types +import {AppState} from 'src/types/v2' +import {ILabel} from '@influxdata/influx' + +interface OwnProps { collector: Telegraf bucket: string onDelete: (telegraf: Telegraf) => void @@ -31,7 +36,13 @@ interface Props { onFilterChange: (searchTerm: string) => void } -export default class CollectorRow extends PureComponent { +interface StateProps { + labels: ILabel[] +} + +type Props = OwnProps & StateProps + +class CollectorRow extends PureComponent { public render() { const {collector, bucket} = this.props @@ -106,3 +117,12 @@ export default class CollectorRow extends PureComponent { this.props.onOpenInstructions(this.props.collector.id) } } + +const mstp = ({labels: {list}}: AppState): StateProps => { + return {labels: list} +} + +export default connect( + mstp, + null +)(CollectorRow) diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index c3391a8750..c5c59c9ca1 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -20,12 +20,11 @@ import {EmptyState, Grid, Input, InputType, Tabs} from 'src/clockface' import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' import FilterList from 'src/shared/components/Filter' import NoBucketsWarning from 'src/organizations/components/NoBucketsWarning' -// APIS -import {client} from 'src/utils/api' +import GetLabels from 'src/configuration/components/GetLabels' // Actions -import * as NotificationsActions from 'src/types/actions/notifications' import {setBucketInfo} from 'src/dataLoaders/actions/steps' +import {updateTelegraf, deleteTelegraf} from 'src/telegrafs/actions' // Decorators import {ErrorHandling} from 'src/shared/decorators/errors' @@ -40,17 +39,9 @@ import { clearDataLoaders, } from 'src/dataLoaders/actions/dataLoaders' import {DataLoaderType} from 'src/types/v2/dataLoaders' -import { - telegrafUpdateSuccess, - telegrafUpdateFailed, - telegrafDeleteSuccess, - telegrafDeleteFailed, -} from 'src/shared/copy/v2/notifications' interface OwnProps { collectors: Telegraf[] - onChange: () => void - notify: NotificationsActions.PublishNotificationActionCreator orgName: string buckets: Bucket[] } @@ -61,6 +52,8 @@ interface DispatchProps { onSetTelegrafConfigID: typeof setTelegrafConfigID onSetTelegrafConfigName: typeof setTelegrafConfigName onClearDataLoaders: typeof clearDataLoaders + onUpdateTelegraf: typeof updateTelegraf + onDeleteTelegraf: typeof deleteTelegraf } type Props = OwnProps & DispatchProps @@ -112,23 +105,25 @@ export class Collectors extends PureComponent { visible={this.hasNoBuckets} resourceName="Telegraf Configurations" /> - - searchTerm={searchTerm} - searchKeys={['plugins.0.config.bucket', 'labels[].name']} - list={collectors} - > - {cs => ( - - )} - + + + searchTerm={searchTerm} + searchKeys={['plugins.0.config.bucket', 'labels[].name']} + list={collectors} + > + {cs => ( + + )} + + { private handleDismissDataLoaders = () => { this.setState({dataLoaderOverlay: OverlayState.Closed}) - this.props.onChange() } private get emptyState(): JSX.Element { @@ -293,27 +287,11 @@ export class Collectors extends PureComponent { } private handleDeleteTelegraf = async (telegraf: Telegraf) => { - const {onChange, notify} = this.props - try { - await client.telegrafConfigs.delete(telegraf.id) - onChange() - notify(telegrafDeleteSuccess(telegraf.name)) - } catch (e) { - console.error(e) - notify(telegrafDeleteFailed(telegraf.name)) - } + await this.props.onDeleteTelegraf(telegraf.id, telegraf.name) } private handleUpdateTelegraf = async (telegraf: Telegraf) => { - const {onChange, notify} = this.props - try { - await client.telegrafConfigs.update(telegraf.id, telegraf) - onChange() - notify(telegrafUpdateSuccess(telegraf.name)) - } catch (e) { - console.error(e) - notify(telegrafUpdateFailed(telegraf.name)) - } + await this.props.onUpdateTelegraf(telegraf) } private handleFilterChange = (e: ChangeEvent): void => { @@ -335,6 +313,8 @@ const mdtp: DispatchProps = { onSetTelegrafConfigID: setTelegrafConfigID, onSetTelegrafConfigName: setTelegrafConfigName, onClearDataLoaders: clearDataLoaders, + onUpdateTelegraf: updateTelegraf, + onDeleteTelegraf: deleteTelegraf, } export default connect( diff --git a/ui/src/organizations/components/__snapshots__/Collectors.test.tsx.snap b/ui/src/organizations/components/__snapshots__/Collectors.test.tsx.snap index 3b78ca2693..1314eb9028 100644 --- a/ui/src/organizations/components/__snapshots__/Collectors.test.tsx.snap +++ b/ui/src/organizations/components/__snapshots__/Collectors.test.tsx.snap @@ -24,7 +24,7 @@ exports[`CollectorList rendering renders 1`] = ` columnCount={3} emptyState={} > - - { return client.buckets.getAllByOrg(org.name) } -const getCollectors = async (org: Organization) => { - return client.telegrafConfigs.getAllByOrg(org) -} interface RouterProps { params: { @@ -38,22 +37,44 @@ interface RouterProps { interface DispatchProps { notify: NotificationsActions.PublishNotificationActionCreator + getOrgTelegrafs: typeof getOrgTelegrafs } interface StateProps { org: Organization + telegrafs: Telegraf[] } type Props = WithRouterProps & RouterProps & DispatchProps & StateProps +interface State { + loading: RemoteDataState +} + @ErrorHandling -class OrgTelegrafsIndex extends Component { - constructor(props) { +class OrgTelegrafsIndex extends Component { + constructor(props: Props) { super(props) + + this.state = {loading: RemoteDataState.NotStarted} + } + + public async componentDidMount() { + const {org} = this.props + + this.setState({loading: RemoteDataState.Loading}) + try { + await this.props.getOrgTelegrafs(org) + this.setState({loading: RemoteDataState.Done}) + } catch (error) { + //TODO: notify of errors + this.setState({loading: RemoteDataState.Error}) + } } public render() { - const {org, notify} = this.props + const {org, telegrafs} = this.props + const {loading: loadingTelegrafs} = this.state return ( @@ -68,37 +89,28 @@ class OrgTelegrafsIndex extends Component { url="telegrafs" title="Telegraf" > - - organization={org} - fetcher={getCollectors} + } > - {(collectors, loading, fetch) => ( - } - > - - organization={org} - fetcher={getBuckets} + + organization={org} + fetcher={getBuckets} + > + {(buckets, loadingBuckets) => ( + } > - {(buckets, loading) => ( - } - > - - - )} - - - )} - + + + )} + + @@ -109,16 +121,21 @@ class OrgTelegrafsIndex extends Component { } } -const mstp = (state: AppState, props: WithRouterProps) => { - const {orgs} = state +const mstp = (state: AppState, props: WithRouterProps): StateProps => { + const { + orgs, + telegrafs: {list}, + } = state const org = orgs.find(o => o.id === props.params.orgID) return { org, + telegrafs: list, } } const mdtp: DispatchProps = { notify: notifyActions.notify, + getOrgTelegrafs, } export default connect( diff --git a/ui/src/organizations/reducers/orgView.ts b/ui/src/organizations/reducers/orgView.ts index 4f2c66a634..d40ebef416 100644 --- a/ui/src/organizations/reducers/orgView.ts +++ b/ui/src/organizations/reducers/orgView.ts @@ -1,15 +1,17 @@ -import {ITask as Task} from '@influxdata/influx' +import {ITask as Task, Telegraf} from '@influxdata/influx' import {Dashboard} from 'src/types/v2' import {Actions, ActionTypes} from 'src/organizations/actions/orgView' export interface OrgViewState { tasks: Task[] dashboards: Dashboard[] + telegrafs: Telegraf[] } const defaultState: OrgViewState = { tasks: [], dashboards: [], + telegrafs: [], } export default (state = defaultState, action: Actions): OrgViewState => { diff --git a/ui/src/shared/components/tabbed_page/TabbedPageSection.tsx b/ui/src/shared/components/tabbed_page/TabbedPageSection.tsx index a77301d7e7..8d21784b3e 100644 --- a/ui/src/shared/components/tabbed_page/TabbedPageSection.tsx +++ b/ui/src/shared/components/tabbed_page/TabbedPageSection.tsx @@ -8,7 +8,6 @@ interface Props { id: string title: string url: string - children: JSX.Element } @ErrorHandling diff --git a/ui/src/telegrafs/actions/index.ts b/ui/src/telegrafs/actions/index.ts index aee49f09a3..a3dba58716 100644 --- a/ui/src/telegrafs/actions/index.ts +++ b/ui/src/telegrafs/actions/index.ts @@ -3,7 +3,7 @@ import {client} from 'src/utils/api' // Types import {RemoteDataState} from 'src/types' -import {Telegraf} from '@influxdata/influx' +import {Telegraf, Organization} from '@influxdata/influx' import {Dispatch} from 'redux-thunk' // Actions @@ -82,6 +82,20 @@ export const getTelegrafs = () => async (dispatch: Dispatch) => { } } +export const getOrgTelegrafs = (org: Organization) => async dispatch => { + try { + dispatch(setTelegrafs(RemoteDataState.Loading)) + + const telegrafs = await client.telegrafConfigs.getAllByOrg(org) + + dispatch(setTelegrafs(RemoteDataState.Done, telegrafs)) + } catch (e) { + console.error(e) + dispatch(setTelegrafs(RemoteDataState.Error)) + dispatch(notify(telegrafGetFailed())) + } +} + export const createTelegraf = (telegraf: Telegraf) => async ( dispatch: Dispatch ) => {