diff options
Diffstat (limited to 'webapp/components/user_settings/manage_incoming_hooks.jsx')
-rw-r--r-- | webapp/components/user_settings/manage_incoming_hooks.jsx | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/webapp/components/user_settings/manage_incoming_hooks.jsx b/webapp/components/user_settings/manage_incoming_hooks.jsx new file mode 100644 index 000000000..b61b331ce --- /dev/null +++ b/webapp/components/user_settings/manage_incoming_hooks.jsx @@ -0,0 +1,225 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Client from 'utils/client.jsx'; +import * as Utils from 'utils/utils.jsx'; +import Constants from 'utils/constants.jsx'; +import ChannelStore from 'stores/channel_store.jsx'; +import LoadingScreen from '../loading_screen.jsx'; + +import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; + +import React from 'react'; + +export default class ManageIncomingHooks extends React.Component { + constructor() { + super(); + + this.getHooks = this.getHooks.bind(this); + this.addNewHook = this.addNewHook.bind(this); + this.updateChannelId = this.updateChannelId.bind(this); + + this.state = {hooks: [], channelId: ChannelStore.getByName(Constants.DEFAULT_CHANNEL).id, getHooksComplete: false}; + } + componentDidMount() { + this.getHooks(); + } + addNewHook() { + const hook = {}; + hook.channel_id = this.state.channelId; + + Client.addIncomingHook( + hook, + (data) => { + let hooks = this.state.hooks; + if (!hooks) { + hooks = []; + } + hooks.push(data); + this.setState({hooks}); + }, + (err) => { + this.setState({serverError: err}); + } + ); + } + removeHook(id) { + const data = {}; + data.id = id; + + Client.deleteIncomingHook( + data, + () => { + const hooks = this.state.hooks; + let index = -1; + for (let i = 0; i < hooks.length; i++) { + if (hooks[i].id === id) { + index = i; + break; + } + } + + if (index !== -1) { + hooks.splice(index, 1); + } + + this.setState({hooks}); + }, + (err) => { + this.setState({serverError: err}); + } + ); + } + getHooks() { + Client.listIncomingHooks( + (data) => { + const state = this.state; + + if (data) { + state.hooks = data; + } + + state.getHooksComplete = true; + this.setState(state); + }, + (err) => { + this.setState({serverError: err}); + } + ); + } + updateChannelId(e) { + this.setState({channelId: e.target.value}); + } + render() { + let serverError; + if (this.state.serverError) { + serverError = <label className='has-error'>{this.state.serverError}</label>; + } + + const channels = ChannelStore.getAll(); + const options = []; + channels.forEach((channel) => { + if (channel.type !== Constants.DM_CHANNEL) { + options.push( + <option + key={'incoming-hook' + channel.id} + value={channel.id} + > + {channel.display_name} + </option> + ); + } + }); + + let disableButton = ''; + if (this.state.channelId === '') { + disableButton = ' disable'; + } + + const hooks = []; + this.state.hooks.forEach((hook) => { + const c = ChannelStore.get(hook.channel_id); + if (c) { + hooks.push( + <div + key={hook.id} + className='webhook__item' + > + <div className='padding-top x2 webhook__url'> + <strong>{'URL: '}</strong> + <span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span> + </div> + <div className='padding-top'> + <strong> + <FormattedMessage + id='user.settings.hooks_in.channel' + defaultMessage='Channel: ' + /> + </strong>{c.display_name} + </div> + <a + className={'webhook__remove'} + href='#' + onClick={this.removeHook.bind(this, hook.id)} + > + <span aria-hidden='true'>{'×'}</span> + </a> + <div className='padding-top x2 divider-light'></div> + </div> + ); + } + }); + + let displayHooks; + if (!this.state.getHooksComplete) { + displayHooks = <LoadingScreen/>; + } else if (hooks.length > 0) { + displayHooks = hooks; + } else { + displayHooks = ( + <div className='padding-top x2'> + <FormattedMessage + id='user.settings.hooks_in.none' + defaultMessage='None' + /> + </div> + ); + } + + const existingHooks = ( + <div className='webhooks__container'> + <label className='control-label padding-top x2'> + <FormattedMessage + id='user.settings.hooks_in.existing' + defaultMessage='Existing incoming webhooks' + /> + </label> + <div className='padding-top divider-light'></div> + <div className='webhooks__list'> + {displayHooks} + </div> + </div> + ); + + return ( + <div key='addIncomingHook'> + <FormattedHTMLMessage + id='user.settings.hooks_in.description' + defaultMessage='Create webhook URLs for use in external integrations. Please see <a href="http://docs.mattermost.com/developer/webhooks-incoming.html" target="_blank">incoming webhooks documentation</a> to learn more. View all incoming webhooks configured on this team below.' + /> + <div><label className='control-label padding-top x2'> + <FormattedMessage + id='user.settings.hooks_in.addTitle' + defaultMessage='Add a new incoming webhook' + /> + </label></div> + <div className='row padding-top'> + <div className='col-sm-10 padding-bottom'> + <select + ref='channelName' + className='form-control' + value={this.state.channelId} + onChange={this.updateChannelId} + > + {options} + </select> + {serverError} + </div> + <div className='col-sm-2 col-xs-4 no-padding--left padding-bottom'> + <a + className={'btn form-control no-padding btn-sm btn-primary' + disableButton} + href='#' + onClick={this.addNewHook} + > + <FormattedMessage + id='user.settings.hooks_in.add' + defaultMessage='Add' + /> + </a> + </div> + </div> + {existingHooks} + </div> + ); + } +} |