diff --git a/js/actions/webhook_actions.js b/js/actions/webhook_actions.js new file mode 100644 index 00000000..4e5b2462 --- /dev/null +++ b/js/actions/webhook_actions.js @@ -0,0 +1,47 @@ +'use strict'; + +import { alt } from '../alt'; +import WebhookFetcher from '../fetchers/webhook_fetcher'; + + +class WebhookActions { + constructor() { + this.generateActions( + 'updateWebhooks', + 'updateEvents', + 'removeWebhook' + ); + } + + fetchWebhooks() { + WebhookFetcher.fetch() + .then((res) => { + this.actions.updateWebhooks(res.webhooks); + }) + .catch((err) => { + console.logGlobal(err); + }); + } + + fetchWebhookEvents() { + WebhookFetcher.fetchEvents() + .then((res) => { + this.actions.updateEvents(res.events); + }) + .catch((err) => { + console.logGlobal(err); + }); + } + + deleteWebhook(id){ + WebhookFetcher.deleteWebhook(id) + .then((res) => { + this.actions.removeWebhook(id); + }) + .catch((err) => { + console.logGlobal(err); + }); + } +} + +export default alt.createActions(WebhookActions); diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 5b05e708..35a6fbe5 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -11,6 +11,7 @@ import WhitelabelActions from '../../actions/whitelabel_actions'; import AccountSettings from './account_settings'; import BitcoinWalletSettings from './bitcoin_wallet_settings'; import APISettings from './api_settings'; +import WebhookSettings from './webhook_settings'; import AclProxy from '../acl_proxy'; @@ -70,6 +71,7 @@ let SettingsContainer = React.createClass({ aclName="acl_view_settings_api"> + diff --git a/js/components/ascribe_settings/webhook_settings.js b/js/components/ascribe_settings/webhook_settings.js new file mode 100644 index 00000000..1f9eefc5 --- /dev/null +++ b/js/components/ascribe_settings/webhook_settings.js @@ -0,0 +1,151 @@ +'use strict'; + +import React from 'react'; + +import WebhookStore from '../../stores/webhook_store'; +import WebhookActions from '../../actions/webhook_actions'; + +import GlobalNotificationModel from '../../models/global_notification_model'; +import GlobalNotificationActions from '../../actions/global_notification_actions'; + +import Form from '../ascribe_forms/form'; +import Property from '../ascribe_forms/property'; + +import ActionPanel from '../ascribe_panel/action_panel'; +import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; + +import ApiUrls from '../../constants/api_urls'; +import AscribeSpinner from '../ascribe_spinner'; + +import { getLangText } from '../../utils/lang_utils'; + + +let WebhookSettings = React.createClass({ + propTypes: { + defaultExpanded: React.PropTypes.bool + }, + + getInitialState() { + return WebhookStore.getState(); + }, + + componentDidMount() { + WebhookStore.listen(this.onChange); + WebhookActions.fetchWebhooks(); + WebhookActions.fetchWebhookEvents(); + }, + + componentWillUnmount() { + WebhookStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + onDeleteWebhook(event) { + let webhookId = event.target.getAttribute('data-id'); + WebhookActions.deleteWebhook(webhookId); + + let notification = new GlobalNotificationModel(getLangText('Webhook deleted'), 'success', 2000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + + handleCreateSuccess() { + WebhookActions.fetchWebhooks(); + let notification = new GlobalNotificationModel(getLangText('Webhook successfully created'), 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + + getWebhooks(){ + let content = ; + + if (this.state.webhooks.length > -1) { + content = this.state.webhooks.map(function(webhook, i) { + const event = webhook.event.split('.')[0]; + return ( + +
+ {event.toUpperCase()} +
+
+ {webhook.target} +
+ + } + buttons={ +
+
+ +
+
+ }/> + ); + }, this); + } + return content; + }, + + getEvents() { + if (this.state.events && this.state.events.length > 1) { + return ( + + + ); + } + return null; + }, + + + render() { + return ( + +
+ { this.getEvents() } + + + +
+
+
+                    Usage: curl <url> -H 'Authorization: Bearer <token>'
+                
+ {this.getWebhooks()} +
+ ); + } +}); + +export default WebhookSettings; \ No newline at end of file diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index a07f29b1..e7f11141 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -72,6 +72,9 @@ let ApiUrls = { 'users_username': AppConstants.apiEndpoint + 'users/username/', 'users_profile': AppConstants.apiEndpoint + 'users/profile/', 'wallet_settings': AppConstants.apiEndpoint + 'users/wallet_settings/', + 'webhook': AppConstants.apiEndpoint + 'webhooks/${webhook_id}/', + 'webhooks': AppConstants.apiEndpoint + 'webhooks/', + 'webhooks_events': AppConstants.apiEndpoint + 'webhooks/events/', 'whitelabel_settings': AppConstants.apiEndpoint + 'whitelabel/settings/${subdomain}/', 'delete_s3_file': AppConstants.serverUrl + 's3/delete/', 'prize_list': AppConstants.apiEndpoint + 'prize/' diff --git a/js/fetchers/webhook_fetcher.js b/js/fetchers/webhook_fetcher.js new file mode 100644 index 00000000..20775c81 --- /dev/null +++ b/js/fetchers/webhook_fetcher.js @@ -0,0 +1,23 @@ +'use strict'; + +import requests from '../utils/requests'; + +let WebhookFetcher = { + /** + * Fetch the registered webhooks of a user from the API. + */ + fetch() { + return requests.get('webhooks'); + }, + + deleteWebhook(id) { + return requests.delete('webhook', {'webhook_id': id }); + }, + + fetchEvents() { + return requests.get('webhooks_events'); + } + +}; + +export default WebhookFetcher; diff --git a/js/stores/webhook_store.js b/js/stores/webhook_store.js new file mode 100644 index 00000000..95b081a6 --- /dev/null +++ b/js/stores/webhook_store.js @@ -0,0 +1,27 @@ +'use strict'; + +import { alt } from '../alt'; +import WebhookActions from '../actions/webhook_actions'; + + +class WebhookStore { + constructor() { + this.webhooks = {}; + this.events = {}; + this.bindActions(WebhookActions); + } + + onUpdateWebhooks(webhooks) { + this.webhooks = webhooks; + } + + onUpdateEvents(events) { + this.events = events; + } + + onRemoveWebhook(id) { + this.webhooks = this.webhooks.filter((webhook) => webhook.id !== parseInt(id)); + } +} + +export default alt.createStore(WebhookStore, 'WebhookStore');