1import React, { PureComponent } from 'react'; 2import { MapDispatchToProps, MapStateToProps } from 'react-redux'; 3import { NavModel } from '@grafana/data'; 4import { config } from '@grafana/runtime'; 5import { Form, Spinner } from '@grafana/ui'; 6import Page from 'app/core/components/Page/Page'; 7import { connectWithCleanUp } from 'app/core/components/connectWithCleanUp'; 8import { NotificationChannelForm } from './components/NotificationChannelForm'; 9import { loadNotificationChannel, testNotificationChannel, updateNotificationChannel } from './state/actions'; 10import { getNavModel } from 'app/core/selectors/navModel'; 11import { mapChannelsToSelectableValue, transformSubmitData, transformTestData } from './utils/notificationChannels'; 12import { NotificationChannelType, NotificationChannelDTO, StoreState } from 'app/types'; 13import { resetSecureField } from './state/reducers'; 14import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; 15 16interface OwnProps extends GrafanaRouteComponentProps<{ id: string }> {} 17 18interface ConnectedProps { 19 navModel: NavModel; 20 notificationChannel: any; 21 notificationChannelTypes: NotificationChannelType[]; 22} 23 24interface DispatchProps { 25 loadNotificationChannel: typeof loadNotificationChannel; 26 testNotificationChannel: typeof testNotificationChannel; 27 updateNotificationChannel: typeof updateNotificationChannel; 28 resetSecureField: typeof resetSecureField; 29} 30 31type Props = OwnProps & ConnectedProps & DispatchProps; 32 33export class EditNotificationChannelPage extends PureComponent<Props> { 34 componentDidMount() { 35 this.props.loadNotificationChannel(parseInt(this.props.match.params.id, 10)); 36 } 37 38 onSubmit = (formData: NotificationChannelDTO) => { 39 const { notificationChannel } = this.props; 40 41 this.props.updateNotificationChannel({ 42 /* 43 Some settings which lives in a collapsed section will not be registered since 44 the section will not be rendered if a user doesn't expand it. Therefore we need to 45 merge the initialData with any changes from the form. 46 */ 47 ...transformSubmitData({ 48 ...notificationChannel, 49 ...formData, 50 settings: { ...notificationChannel.settings, ...formData.settings }, 51 }), 52 id: notificationChannel.id, 53 }); 54 }; 55 56 onTestChannel = (formData: NotificationChannelDTO) => { 57 const { notificationChannel } = this.props; 58 /* 59 Same as submit 60 */ 61 this.props.testNotificationChannel( 62 transformTestData({ 63 ...notificationChannel, 64 ...formData, 65 settings: { ...notificationChannel.settings, ...formData.settings }, 66 }) 67 ); 68 }; 69 70 render() { 71 const { navModel, notificationChannel, notificationChannelTypes } = this.props; 72 73 return ( 74 <Page navModel={navModel}> 75 <Page.Contents> 76 <h2 className="page-sub-heading">Edit notification channel</h2> 77 {notificationChannel && notificationChannel.id > 0 ? ( 78 <Form 79 maxWidth={600} 80 onSubmit={this.onSubmit} 81 defaultValues={{ 82 ...notificationChannel, 83 type: notificationChannelTypes.find((n) => n.value === notificationChannel.type), 84 }} 85 > 86 {({ control, errors, getValues, register, watch }) => { 87 const selectedChannel = notificationChannelTypes.find((c) => c.value === getValues().type.value); 88 89 return ( 90 <NotificationChannelForm 91 selectableChannels={mapChannelsToSelectableValue(notificationChannelTypes, true)} 92 selectedChannel={selectedChannel} 93 imageRendererAvailable={config.rendererAvailable} 94 onTestChannel={this.onTestChannel} 95 register={register} 96 watch={watch} 97 errors={errors} 98 getValues={getValues} 99 control={control} 100 resetSecureField={this.props.resetSecureField} 101 secureFields={notificationChannel.secureFields} 102 /> 103 ); 104 }} 105 </Form> 106 ) : ( 107 <div> 108 Loading notification channel 109 <Spinner /> 110 </div> 111 )} 112 </Page.Contents> 113 </Page> 114 ); 115 } 116} 117 118const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state) => { 119 return { 120 navModel: getNavModel(state.navIndex, 'channels'), 121 notificationChannel: state.notificationChannel.notificationChannel, 122 notificationChannelTypes: state.notificationChannel.notificationChannelTypes, 123 }; 124}; 125 126const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = { 127 loadNotificationChannel, 128 testNotificationChannel, 129 updateNotificationChannel, 130 resetSecureField, 131}; 132 133export default connectWithCleanUp( 134 mapStateToProps, 135 mapDispatchToProps, 136 (state) => state.notificationChannel 137)(EditNotificationChannelPage); 138