diff --git a/ui/src/organizations/apis/index.ts b/ui/src/organizations/apis/index.ts index e26c8ef621..849e0b2075 100644 --- a/ui/src/organizations/apis/index.ts +++ b/ui/src/organizations/apis/index.ts @@ -169,3 +169,20 @@ export const getCollectors = async (org: Organization): Promise<Telegraf[]> => { console.error(error) } } + +export const getTelegrafConfigTOML = async ( + telegrafID: string +): Promise<string> => { + const options = { + headers: { + Accept: 'application/toml', + }, + } + + const response = await telegrafsAPI.telegrafsTelegrafIDGet( + telegrafID, + options + ) + + return response.data as string // response.data is string with 'application/toml' header +} diff --git a/ui/src/organizations/components/CollectorList.tsx b/ui/src/organizations/components/CollectorList.tsx index 808b9bfd64..4f125566af 100644 --- a/ui/src/organizations/components/CollectorList.tsx +++ b/ui/src/organizations/components/CollectorList.tsx @@ -13,6 +13,7 @@ import {getDeep} from 'src/utils/wrappers' interface Props { collectors: Telegraf[] emptyState: JSX.Element + onDownloadConfig: (telegrafID: string) => void } export default class BucketList extends PureComponent<Props> { @@ -35,13 +36,15 @@ export default class BucketList extends PureComponent<Props> { } public get collectorsList(): JSX.Element[] { - const {collectors} = this.props + const {collectors, onDownloadConfig} = this.props if (collectors !== undefined) { return collectors.map(collector => ( <CollectorRow + key={collector.id} collector={collector} bucket={getDeep<string>(collector, 'plugins.0.config.bucket', '')} + onDownloadConfig={onDownloadConfig} /> )) } diff --git a/ui/src/organizations/components/CollectorRow.tsx b/ui/src/organizations/components/CollectorRow.tsx index 251afeafd1..9cbb12ae29 100644 --- a/ui/src/organizations/components/CollectorRow.tsx +++ b/ui/src/organizations/components/CollectorRow.tsx @@ -9,12 +9,14 @@ import { Alignment, Button, ComponentColor, + ComponentSpacer, } from 'src/clockface' import {Telegraf} from 'src/api' interface Props { collector: Telegraf bucket: string + onDownloadConfig: (telegrafID: string) => void } export default class BucketRow extends PureComponent<Props> { @@ -25,22 +27,27 @@ export default class BucketRow extends PureComponent<Props> { <IndexList.Row> <IndexList.Cell>{collector.name}</IndexList.Cell> <IndexList.Cell>{bucket}</IndexList.Cell> - <IndexList.Cell> - <Button - size={ComponentSize.Small} - color={ComponentColor.Secondary} - text={'Download Config'} - /> - </IndexList.Cell> <IndexList.Cell revealOnHover={true} alignment={Alignment.Right}> - <ConfirmationButton - size={ComponentSize.ExtraSmall} - text="Delete" - confirmText="Confirm" - /> + <ComponentSpacer align={Alignment.Right}> + <Button + size={ComponentSize.ExtraSmall} + color={ComponentColor.Secondary} + text={'Download Config'} + onClick={this.handleDownloadConfig} + /> + <ConfirmationButton + size={ComponentSize.ExtraSmall} + text="Delete" + confirmText="Confirm" + /> + </ComponentSpacer> </IndexList.Cell> </IndexList.Row> </> ) } + + private handleDownloadConfig = (): void => { + this.props.onDownloadConfig(this.props.collector.id) + } } diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index 067a520666..0a9fd8de68 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -1,10 +1,12 @@ // Libraries import React, {PureComponent} from 'react' +// Utils +import {downloadTextFile} from 'src/shared/utils/download' + // Components import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader' import CollectorList from 'src/organizations/components/CollectorList' - import { Button, ComponentColor, @@ -13,12 +15,22 @@ import { EmptyState, } from 'src/clockface' +// Actions +import * as NotificationsActions from 'src/types/actions/notifications' + +// Constants +import {getTelegrafConfigFailed} from 'src/shared/copy/v2/notifications' + // Decorators import {ErrorHandling} from 'src/shared/decorators/errors' import {Telegraf} from 'src/api' +import {getTelegrafConfigTOML} from 'src/organizations/apis/index' +import {notify} from 'src/shared/actions/notifications' interface Props { collectors: Telegraf[] + onChange: () => void + notify: NotificationsActions.PublishNotificationActionCreator } @ErrorHandling @@ -35,7 +47,11 @@ export default class OrgOptions extends PureComponent<Props> { color={ComponentColor.Primary} /> </TabbedPageHeader> - <CollectorList collectors={collectors} emptyState={this.emptyState} /> + <CollectorList + collectors={collectors} + emptyState={this.emptyState} + onDownloadConfig={this.handleDownloadConfig} + /> </> ) } @@ -46,4 +62,13 @@ export default class OrgOptions extends PureComponent<Props> { </EmptyState> ) } + + private handleDownloadConfig = async (telegrafID: string) => { + try { + const config = await getTelegrafConfigTOML(telegrafID) + downloadTextFile(config, 'config.toml') + } catch (error) { + notify(getTelegrafConfigFailed()) + } + } } diff --git a/ui/src/organizations/containers/OrganizationView.tsx b/ui/src/organizations/containers/OrganizationView.tsx index c088cfcfbf..d942c2f8d6 100644 --- a/ui/src/organizations/containers/OrganizationView.tsx +++ b/ui/src/organizations/containers/OrganizationView.tsx @@ -16,6 +16,7 @@ import { // Actions import {updateOrg} from 'src/organizations/actions' +import * as notifyActions from 'src/shared/actions/notifications' // Components import {Page} from 'src/pageLayout' @@ -34,6 +35,7 @@ import RenamablePageTitle from 'src/pageLayout/components/RenamablePageTitle' // Types import {AppState, Dashboard} from 'src/types/v2' import {ResourceOwner, Bucket, Organization, Task, Telegraf} from 'src/api' +import * as NotificationsActions from 'src/types/actions/notifications' // Decorators import {ErrorHandling} from 'src/shared/decorators/errors' @@ -44,6 +46,7 @@ interface StateProps { interface DispatchProps { onUpdateOrg: typeof updateOrg + notify: NotificationsActions.PublishNotificationActionCreator } type Props = StateProps & WithRouterProps & DispatchProps @@ -51,7 +54,7 @@ type Props = StateProps & WithRouterProps & DispatchProps @ErrorHandling class OrganizationView extends PureComponent<Props> { public render() { - const {org, params} = this.props + const {org, params, notify} = this.props return ( <Page titleTag={org.name}> @@ -143,9 +146,13 @@ class OrganizationView extends PureComponent<Props> { organization={org} fetcher={getCollectors} > - {(collectors, loading) => ( + {(collectors, loading, fetch) => ( <Spinner loading={loading}> - <Collectors collectors={collectors} /> + <Collectors + collectors={collectors} + onChange={fetch} + notify={notify} + /> </Spinner> )} </GetOrgResources> @@ -189,6 +196,7 @@ const mstp = (state: AppState, props: WithRouterProps) => { const mdtp: DispatchProps = { onUpdateOrg: updateOrg, + notify: notifyActions.notify, } export default connect<StateProps, DispatchProps, {}>(