Update telegrafs in orgs view to use redux
parent
1797ec6a5e
commit
5bc0ddc67c
|
@ -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 {
|
||||
|
|
|
@ -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<Props> {
|
|||
}
|
||||
|
||||
private handleFormSubmit = async () => {
|
||||
const {onSaveTelegrafConfig, telegrafConfigID, notify} = this.props
|
||||
const {onSaveTelegrafConfig, telegrafConfigID} = this.props
|
||||
|
||||
await onSaveTelegrafConfig()
|
||||
|
||||
notify(TelegrafConfigCreationSuccess)
|
||||
|
||||
if (!telegrafConfigID) {
|
||||
this.handleCreateDashboardsForPlugins()
|
||||
}
|
||||
|
|
|
@ -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<Props> {
|
||||
interface StateProps {
|
||||
labels: ILabel[]
|
||||
}
|
||||
|
||||
type Props = OwnProps & StateProps
|
||||
|
||||
class CollectorRow extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {collector, bucket} = this.props
|
||||
|
||||
|
@ -106,3 +117,12 @@ export default class CollectorRow extends PureComponent<Props> {
|
|||
this.props.onOpenInstructions(this.props.collector.id)
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = ({labels: {list}}: AppState): StateProps => {
|
||||
return {labels: list}
|
||||
}
|
||||
|
||||
export default connect<StateProps, {}, OwnProps>(
|
||||
mstp,
|
||||
null
|
||||
)(CollectorRow)
|
||||
|
|
|
@ -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<Props, State> {
|
|||
visible={this.hasNoBuckets}
|
||||
resourceName="Telegraf Configurations"
|
||||
/>
|
||||
<FilterList<Telegraf>
|
||||
searchTerm={searchTerm}
|
||||
searchKeys={['plugins.0.config.bucket', 'labels[].name']}
|
||||
list={collectors}
|
||||
>
|
||||
{cs => (
|
||||
<CollectorList
|
||||
collectors={cs}
|
||||
emptyState={this.emptyState}
|
||||
onDelete={this.handleDeleteTelegraf}
|
||||
onUpdate={this.handleUpdateTelegraf}
|
||||
onOpenInstructions={this.handleOpenInstructions}
|
||||
onOpenTelegrafConfig={this.handleOpenTelegrafConfig}
|
||||
onFilterChange={this.handleFilterUpdate}
|
||||
/>
|
||||
)}
|
||||
</FilterList>
|
||||
<GetLabels>
|
||||
<FilterList<Telegraf>
|
||||
searchTerm={searchTerm}
|
||||
searchKeys={['plugins.0.config.bucket', 'labels[].name']}
|
||||
list={collectors}
|
||||
>
|
||||
{cs => (
|
||||
<CollectorList
|
||||
collectors={cs}
|
||||
emptyState={this.emptyState}
|
||||
onDelete={this.handleDeleteTelegraf}
|
||||
onUpdate={this.handleUpdateTelegraf}
|
||||
onOpenInstructions={this.handleOpenInstructions}
|
||||
onOpenTelegrafConfig={this.handleOpenTelegrafConfig}
|
||||
onFilterChange={this.handleFilterUpdate}
|
||||
/>
|
||||
)}
|
||||
</FilterList>
|
||||
</GetLabels>
|
||||
</Grid.Column>
|
||||
<Grid.Column
|
||||
widthSM={Columns.Six}
|
||||
|
@ -266,7 +261,6 @@ export class Collectors extends PureComponent<Props, State> {
|
|||
|
||||
private handleDismissDataLoaders = () => {
|
||||
this.setState({dataLoaderOverlay: OverlayState.Closed})
|
||||
this.props.onChange()
|
||||
}
|
||||
|
||||
private get emptyState(): JSX.Element {
|
||||
|
@ -293,27 +287,11 @@ export class Collectors extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
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<HTMLInputElement>): void => {
|
||||
|
@ -335,6 +313,8 @@ const mdtp: DispatchProps = {
|
|||
onSetTelegrafConfigID: setTelegrafConfigID,
|
||||
onSetTelegrafConfigName: setTelegrafConfigName,
|
||||
onClearDataLoaders: clearDataLoaders,
|
||||
onUpdateTelegraf: updateTelegraf,
|
||||
onDeleteTelegraf: deleteTelegraf,
|
||||
}
|
||||
|
||||
export default connect<null, DispatchProps, OwnProps>(
|
||||
|
|
|
@ -24,7 +24,7 @@ exports[`CollectorList rendering renders 1`] = `
|
|||
columnCount={3}
|
||||
emptyState={<React.Fragment />}
|
||||
>
|
||||
<CollectorRow
|
||||
<Connect(CollectorRow)
|
||||
bucket=""
|
||||
collector={
|
||||
Object {
|
||||
|
@ -39,7 +39,7 @@ exports[`CollectorList rendering renders 1`] = `
|
|||
onOpenTelegrafConfig={[MockFunction]}
|
||||
onUpdate={[MockFunction]}
|
||||
/>
|
||||
<CollectorRow
|
||||
<Connect(CollectorRow)
|
||||
bucket=""
|
||||
collector={
|
||||
Object {
|
||||
|
|
|
@ -18,17 +18,16 @@ import GetOrgResources from 'src/organizations/components/GetOrgResources'
|
|||
// Actions
|
||||
import * as NotificationsActions from 'src/types/actions/notifications'
|
||||
import * as notifyActions from 'src/shared/actions/notifications'
|
||||
import {getOrgTelegrafs} from 'src/telegrafs/actions'
|
||||
|
||||
// Types
|
||||
import {Bucket, Organization, Telegraf} from '@influxdata/influx'
|
||||
import {client} from 'src/utils/api'
|
||||
import {RemoteDataState} from 'src/types'
|
||||
|
||||
const getBuckets = async (org: Organization) => {
|
||||
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<Props> {
|
||||
constructor(props) {
|
||||
class OrgTelegrafsIndex extends Component<Props, State> {
|
||||
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 (
|
||||
<Page titleTag={org.name}>
|
||||
|
@ -68,37 +89,28 @@ class OrgTelegrafsIndex extends Component<Props> {
|
|||
url="telegrafs"
|
||||
title="Telegraf"
|
||||
>
|
||||
<GetOrgResources<Telegraf>
|
||||
organization={org}
|
||||
fetcher={getCollectors}
|
||||
<SpinnerContainer
|
||||
loading={loadingTelegrafs}
|
||||
spinnerComponent={<TechnoSpinner />}
|
||||
>
|
||||
{(collectors, loading, fetch) => (
|
||||
<SpinnerContainer
|
||||
loading={loading}
|
||||
spinnerComponent={<TechnoSpinner />}
|
||||
>
|
||||
<GetOrgResources<Bucket>
|
||||
organization={org}
|
||||
fetcher={getBuckets}
|
||||
<GetOrgResources<Bucket>
|
||||
organization={org}
|
||||
fetcher={getBuckets}
|
||||
>
|
||||
{(buckets, loadingBuckets) => (
|
||||
<SpinnerContainer
|
||||
loading={loadingBuckets}
|
||||
spinnerComponent={<TechnoSpinner />}
|
||||
>
|
||||
{(buckets, loading) => (
|
||||
<SpinnerContainer
|
||||
loading={loading}
|
||||
spinnerComponent={<TechnoSpinner />}
|
||||
>
|
||||
<Collectors
|
||||
collectors={collectors}
|
||||
onChange={fetch}
|
||||
notify={notify}
|
||||
buckets={buckets}
|
||||
orgName={org.name}
|
||||
/>
|
||||
</SpinnerContainer>
|
||||
)}
|
||||
</GetOrgResources>
|
||||
</SpinnerContainer>
|
||||
)}
|
||||
</GetOrgResources>
|
||||
<Collectors
|
||||
collectors={telegrafs}
|
||||
buckets={buckets}
|
||||
orgName={org.name}
|
||||
/>
|
||||
</SpinnerContainer>
|
||||
)}
|
||||
</GetOrgResources>
|
||||
</SpinnerContainer>
|
||||
</TabbedPageSection>
|
||||
</Tabs.TabContents>
|
||||
</Tabs>
|
||||
|
@ -109,16 +121,21 @@ class OrgTelegrafsIndex extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
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<StateProps, DispatchProps, {}>(
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -8,7 +8,6 @@ interface Props {
|
|||
id: string
|
||||
title: string
|
||||
url: string
|
||||
children: JSX.Element
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
|
|
|
@ -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<Action>) => {
|
|||
}
|
||||
}
|
||||
|
||||
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<Action>
|
||||
) => {
|
||||
|
|
Loading…
Reference in New Issue