summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorDavid Lu <david.lu97@outlook.com>2016-08-15 11:10:31 -0400
committerJoram Wilander <jwawilander@gmail.com>2016-08-15 11:10:31 -0400
commitef33f3fcd1fec2b3552293f6cdb8045dcc7d214d (patch)
treeedf24fc65163a8abfeb73506d351605973918ac5 /webapp
parent5e6af8e970829f683f7d80034a8af7bb36644c17 (diff)
downloadchat-ef33f3fcd1fec2b3552293f6cdb8045dcc7d214d.tar.gz
chat-ef33f3fcd1fec2b3552293f6cdb8045dcc7d214d.tar.bz2
chat-ef33f3fcd1fec2b3552293f6cdb8045dcc7d214d.zip
PLT-3005 Added confirmation screen to integrations (#3747)
Diffstat (limited to 'webapp')
-rw-r--r--webapp/actions/oauth_actions.jsx2
-rw-r--r--webapp/components/integrations/components/add_command.jsx6
-rw-r--r--webapp/components/integrations/components/add_incoming_webhook.jsx6
-rw-r--r--webapp/components/integrations/components/add_oauth_app.jsx4
-rw-r--r--webapp/components/integrations/components/add_outgoing_webhook.jsx7
-rw-r--r--webapp/components/integrations/components/confirm_integration.jsx243
-rw-r--r--webapp/components/integrations/components/installed_incoming_webhook.jsx2
-rw-r--r--webapp/i18n/en.json18
-rw-r--r--webapp/routes/route_integrations.jsx6
-rw-r--r--webapp/utils/async_client.jsx6
-rw-r--r--webapp/utils/constants.jsx6
11 files changed, 286 insertions, 20 deletions
diff --git a/webapp/actions/oauth_actions.jsx b/webapp/actions/oauth_actions.jsx
index d2e5b0c98..07b4c2908 100644
--- a/webapp/actions/oauth_actions.jsx
+++ b/webapp/actions/oauth_actions.jsx
@@ -52,7 +52,7 @@ export function registerOAuthApp(app, onSuccess, onError) {
});
if (onSuccess) {
- onSuccess();
+ onSuccess(data);
}
},
onError
diff --git a/webapp/components/integrations/components/add_command.jsx b/webapp/components/integrations/components/add_command.jsx
index 300e55a70..55fe9e121 100644
--- a/webapp/components/integrations/components/add_command.jsx
+++ b/webapp/components/integrations/components/add_command.jsx
@@ -160,8 +160,8 @@ export default class AddCommand extends React.Component {
AsyncClient.addCommand(
command,
- () => {
- browserHistory.push('/' + this.props.team.name + '/integrations/commands');
+ (data) => {
+ browserHistory.push('/' + this.props.team.name + '/integrations/confirm?type=commands&id=' + data.token);
},
(err) => {
this.setState({
@@ -313,7 +313,7 @@ export default class AddCommand extends React.Component {
/>
</Link>
<FormattedMessage
- id='add_command.header'
+ id='integrations.add'
defaultMessage='Add'
/>
</BackstageHeader>
diff --git a/webapp/components/integrations/components/add_incoming_webhook.jsx b/webapp/components/integrations/components/add_incoming_webhook.jsx
index 4a3779aff..fa8a47a9c 100644
--- a/webapp/components/integrations/components/add_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/add_incoming_webhook.jsx
@@ -73,8 +73,8 @@ export default class AddIncomingWebhook extends React.Component {
AsyncClient.addIncomingHook(
hook,
- () => {
- browserHistory.push('/' + this.props.team.name + '/integrations/incoming_webhooks');
+ (data) => {
+ browserHistory.push('/' + this.props.team.name + '/integrations/confirm?type=incoming_webhooks&id=' + data.id);
},
(err) => {
this.setState({
@@ -114,7 +114,7 @@ export default class AddIncomingWebhook extends React.Component {
/>
</Link>
<FormattedMessage
- id='add_incoming_webhook.header'
+ id='integrations.add'
defaultMessage='Add'
/>
</BackstageHeader>
diff --git a/webapp/components/integrations/components/add_oauth_app.jsx b/webapp/components/integrations/components/add_oauth_app.jsx
index 7e56aea8f..4c01c5af0 100644
--- a/webapp/components/integrations/components/add_oauth_app.jsx
+++ b/webapp/components/integrations/components/add_oauth_app.jsx
@@ -144,8 +144,8 @@ export default class AddOAuthApp extends React.Component {
OAuthActions.registerOAuthApp(
app,
- () => {
- browserHistory.push('/' + this.props.team.name + '/integrations/oauth2-apps');
+ (data) => {
+ browserHistory.push('/' + this.props.team.name + '/integrations/confirm?type=oauth2-apps&id=' + data.id);
},
(err) => {
this.setState({
diff --git a/webapp/components/integrations/components/add_outgoing_webhook.jsx b/webapp/components/integrations/components/add_outgoing_webhook.jsx
index 540b565cd..bf0d327ef 100644
--- a/webapp/components/integrations/components/add_outgoing_webhook.jsx
+++ b/webapp/components/integrations/components/add_outgoing_webhook.jsx
@@ -119,8 +119,8 @@ export default class AddOutgoingWebhook extends React.Component {
AsyncClient.addOutgoingHook(
hook,
- () => {
- browserHistory.push('/' + this.props.team.name + '/integrations/outgoing_webhooks');
+ (data) => {
+ browserHistory.push('/' + this.props.team.name + '/integrations/confirm?type=outgoing_webhooks&id=' + data.token);
},
(err) => {
this.setState({
@@ -176,6 +176,7 @@ export default class AddOutgoingWebhook extends React.Component {
render() {
const contentTypeOption1 = 'application/x-www-form-urlencoded';
const contentTypeOption2 = 'application/json';
+
return (
<div className='backstage-content'>
<BackstageHeader>
@@ -186,7 +187,7 @@ export default class AddOutgoingWebhook extends React.Component {
/>
</Link>
<FormattedMessage
- id='add_outgoing_webhook.header'
+ id='integrations.add'
defaultMessage='Add'
/>
</BackstageHeader>
diff --git a/webapp/components/integrations/components/confirm_integration.jsx b/webapp/components/integrations/components/confirm_integration.jsx
new file mode 100644
index 000000000..96e24c575
--- /dev/null
+++ b/webapp/components/integrations/components/confirm_integration.jsx
@@ -0,0 +1,243 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+
+import BackstageHeader from 'components/backstage/components/backstage_header.jsx';
+import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+import {browserHistory, Link} from 'react-router/es6';
+import SpinnerButton from 'components/spinner_button.jsx';
+
+import UserStore from 'stores/user_store.jsx';
+import IntegrationStore from 'stores/integration_store.jsx';
+
+import Constants from 'utils/constants.jsx';
+
+export default class ConfirmIntegration extends React.Component {
+ static get propTypes() {
+ return {
+ team: React.propTypes.object.isRequired,
+ location: React.PropTypes.object
+ };
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.handleDone = this.handleDone.bind(this);
+
+ this.handleIntegrationChange = this.handleIntegrationChange.bind(this);
+
+ const userId = UserStore.getCurrentId();
+
+ this.state = {
+ type: this.props.location.query.type,
+ id: this.props.location.query.id,
+ oauthApps: IntegrationStore.getOAuthApps(userId),
+ loading: !IntegrationStore.hasReceivedOAuthApps(userId)
+ };
+ }
+
+ componentDidMount() {
+ IntegrationStore.addChangeListener(this.handleIntegrationChange);
+ }
+
+ componentWillUnmount() {
+ IntegrationStore.removeChangeListener(this.handleIntegrationChange);
+ }
+
+ handleIntegrationChange() {
+ const userId = UserStore.getCurrentId();
+
+ this.setState({
+ oauthApps: IntegrationStore.getOAuthApps(userId),
+ loading: !IntegrationStore.hasReceivedOAuthApps(userId)
+ });
+ }
+
+ handleDone() {
+ browserHistory.push('/' + this.props.team.name + '/integrations/' + this.state.type);
+ this.setState({
+ id: ''
+ });
+ }
+
+ render() {
+ let headerText = null;
+ let helpText = null;
+ let tokenText = null;
+ if (this.state.type === Constants.Integrations.COMMAND) {
+ headerText = (
+ <FormattedMessage
+ id={'installed_commands.header'}
+ defaultMessage='Slash Commands'
+ />
+ );
+ helpText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_command.doneHelp'
+ defaultMessage='Your slash command has been set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (see <a href="https://docs.mattermost.com/developer/slash-commands.html">documentation</a> for further details).'
+ />
+ </div>
+ );
+ tokenText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_command.token'
+ defaultMessage='<b>Token</b>: {token}'
+ values={{
+ token: this.state.id
+ }}
+ />
+ </div>
+ );
+ } else if (this.state.type === Constants.Integrations.INCOMING_WEBHOOK) {
+ headerText = (
+ <FormattedMessage
+ id={'installed_incoming_webhooks.header'}
+ defaultMessage='Incoming Webhooks'
+ />
+ );
+ helpText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_incoming_webhook.doneHelp'
+ defaultMessage='Your incoming webhook has been set up. Please send data to the following URL (see <a href=\"https://docs.mattermost.com/developer/webhooks-incoming.html\">documentation</a> for further details).'
+ />
+ </div>
+ );
+ tokenText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_incoming_webhook.url'
+ defaultMessage='<b>URL</b>: {url}'
+ values={{
+ url: window.location.origin + '/hooks/' + this.state.id
+ }}
+ />
+ </div>
+ );
+ } else if (this.state.type === Constants.Integrations.OUTGOING_WEBHOOK) {
+ headerText = (
+ <FormattedMessage
+ id={'installed_outgoing_webhooks.header'}
+ defaultMessage='Outgoing Webhooks'
+ />
+ );
+ helpText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_outgoing_webhook.doneHelp'
+ defaultMessage='Your outgoing webhook has been set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (see <a href=\"https://docs.mattermost.com/developer/webhooks-outgoing.html\">documentation</a> for further details).'
+ />
+ </div>
+ );
+ tokenText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_outgoing_webhook.token'
+ defaultMessage='<b>Token</b>: {token}'
+ values={{
+ token: this.state.id
+ }}
+ />
+ </div>
+ );
+ } else if (this.state.type === Constants.Integrations.OAUTH_APP) {
+ let oauthApp = {};
+ for (var i = 0; i < this.state.oauthApps.length; i++) {
+ if (this.state.oauthApps[i].id === this.state.id) {
+ oauthApp = this.state.oauthApps[i];
+ break;
+ }
+ }
+
+ if (oauthApp) {
+ headerText = (
+ <FormattedMessage
+ id={'installed_oauth_apps.header'}
+ defaultMessage='OAuth 2.0 Applications'
+ />
+ );
+
+ helpText = [];
+ helpText.push(
+ <div className='backstage-list__help'>
+ <FormattedMessage
+ id='add_oauth_app.doneHelp'
+ defaultMessage='Your OAuth 2.0 application has been set up. Please use the following Client ID and Client Secret when requesting authorization for your application.'
+ />
+ </div>
+ );
+ helpText.push(
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_oauth_app.clientId'
+ defaultMessage='<b>Client ID:</b> {id}'
+ values={{
+ id: this.state.id
+ }}
+ /> <br/>
+ <FormattedHTMLMessage
+ id='add_oauth_app.clientSecret'
+ defaultMessage='<b>Client Secret:</b> {secret}'
+ values={{
+ secret: oauthApp.client_secret
+ }}
+ />
+ </div>
+ );
+
+ helpText.push(
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_oauth_app.doneUrlHelp'
+ defaultMessage='Please send data to the following URL.'
+ />
+ </div>
+ );
+
+ tokenText = (
+ <div className='backstage-list__help'>
+ <FormattedHTMLMessage
+ id='add_oauth_app.url'
+ defaultMessage='<b>URL(s)</b>: {url}'
+ values={{
+ url: oauthApp.callback_urls
+ }}
+ />
+ </div>
+ );
+ }
+ }
+
+ return (
+ <div className='backstage-content row'>
+ <BackstageHeader>
+ <Link to={'/' + this.props.team.name + '/integrations/' + this.state.type}>
+ {headerText}
+ </Link>
+ <FormattedMessage
+ id='integrations.add'
+ defaultMessage='Add'
+ />
+ </BackstageHeader>
+ {helpText}
+ {tokenText}
+ <div className='backstage-list__help'>
+ <SpinnerButton
+ className='btn btn-primary'
+ type='submit'
+ onClick={this.handleDone}
+ >
+ <FormattedMessage
+ id='integrations.done'
+ defaultMessage='Done'
+ />
+ </SpinnerButton>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/webapp/components/integrations/components/installed_incoming_webhook.jsx b/webapp/components/integrations/components/installed_incoming_webhook.jsx
index 965ed2bc9..2b514d5ec 100644
--- a/webapp/components/integrations/components/installed_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/installed_incoming_webhook.jsx
@@ -102,7 +102,7 @@ export default class InstalledIncomingWebhook extends React.Component {
/>
</span>
</div>
- <div className='tem-details__row'>
+ <div className='item-details__row'>
<span className='item-details__creation'>
<FormattedMessage
id='installed_integrations.creation'
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index d4cb97101..d249d7596 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -42,7 +42,6 @@
"add_command.description.help": "Description for your incoming webhook.",
"add_command.displayName": "Display Name",
"add_command.displayName.help": "Display name for your slash command made of up to 64 characters.",
- "add_command.header": "Add",
"add_command.iconUrl": "Response Icon",
"add_command.iconUrl.help": "(Optional) Choose a profile picture override for the post responses to this slash command. Enter the URL of a .png or .jpg file at least 128 pixels by 128 pixels.",
"add_command.iconUrl.placeholder": "https://www.example.com/myicon.png",
@@ -68,6 +67,8 @@
"add_command.username": "Response Username",
"add_command.username.help": "(Optional) Choose a username override for responses for this slash command. Usernames can consist of up to 22 characters consisting of lowercase letters, numbers and they symbols \"-\", \"_\", and \".\" .",
"add_command.username.placeholder": "Username",
+ "add_command.doneHelp": "Your slash command has been set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (see <a href=\"https://docs.mattermost.com/developer/slash-commands.html\">documentation</a> for further details).",
+ "add_command.token": "<b>Token</b>: {token}",
"add_emoji.cancel": "Cancel",
"add_emoji.header": "Add",
"add_emoji.image": "Image",
@@ -90,7 +91,6 @@
"add_incoming_webhook.description.help": "Description for your incoming webhook.",
"add_incoming_webhook.displayName": "Display Name",
"add_incoming_webhook.displayName.help": "Display name for your incoming webhook made of up to 64 characters.",
- "add_incoming_webhook.header": "Add",
"add_incoming_webhook.name": "Name",
"add_incoming_webhook.save": "Save",
"add_oauth_app.callbackUrls.help": "The redirect URIs to which the service will redirect users after accepting or denying authorization of your application, and which will handle authorization codes or access tokens. Must be a valid URL and start with http:// or https://.",
@@ -104,6 +104,13 @@
"add_oauth_app.name.help": "Display name for your OAuth 2.0 application made of up to 64 characters.",
"add_oauth_app.nameRequired": "Name for the OAuth 2.0 application is required.",
"add_oauth_app.trusted.help": "When true, the OAuth 2.0 application is considered trusted by the Mattermost server and doesn't require the user to accept authorization. When false, an additional window will appear, asking the user to accept or deny the authorization.",
+ "add_oauth_app.doneHelp": "Your OAuth 2.0 application has been set up. Please use the following Client ID and Client Secret when requesting authorization for your application.",
+ "add_oauth_app.doneUrlHelp": "Please send data to the following URL.",
+ "add_oauth_app.clientId": "<b>Client ID</b>: {id}",
+ "add_oauth_app.clientSecret": "<b>Client Secret</b>: {secret}",
+ "add_oauth_app.url": "<b>URL(s)</b>: {url}",
+ "add_incoming_webhook.doneHelp": "Your incoming webhook has been set up. Please send data to the following URL (see <a href=\"https://docs.mattermost.com/developer/webhooks-incoming.html\">documentation</a> for further details).",
+ "add_incoming_webhook.url": "<b>URL</b>: {url}",
"add_outgoing_webhook.callbackUrls": "Callback URLs (One Per Line)",
"add_outgoing_webhook.callbackUrls.help": "The URL that messages will be sent to.",
"add_outgoing_webhook.callbackUrlsRequired": "One or more callback URLs are required",
@@ -118,9 +125,10 @@
"add_outgoing_webhook.description.help": "Description for your outgoing webhook.",
"add_outgoing_webhook.displayName": "Display Name",
"add_outgoing_webhook.displayName.help": "Display name for your outgoing webhook made of up to 64 characters.",
- "add_outgoing_webhook.header": "Add",
"add_outgoing_webhook.name": "Name",
"add_outgoing_webhook.save": "Save",
+ "add_outgoing_webhook.doneHelp": "Your outgoing webhook has been set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (see <a href=\"https://docs.mattermost.com/developer/webhooks-outgoing.html\">documentation</a> for further details).",
+ "add_outgoing_webhook.token": "<b>Token</b>: {token}",
"add_outgoing_webhook.triggerWords": "Trigger Words (One Per Line)",
"add_outgoing_webhook.triggerWords.help": "Messages that start with one of the specified words will trigger the outgoing webhook. Optional if Channel is selected.",
"add_outgoing_webhook.triggerWordsOrChannelRequired": "A valid channel or a list of trigger words is required",
@@ -1187,7 +1195,7 @@
"get_team_invite_link_modal.help": "Send teammates the link below for them to sign-up to this team site. The Team Invite Link can be shared with multiple teammates as it does not change unless it's regenerated in Team Settings by a Team Admin.",
"get_team_invite_link_modal.helpDisabled": "User creation has been disabled for your team. Please ask your team administrator for details.",
"get_team_invite_link_modal.title": "Team Invite Link",
- "installed_command.header": "Slash Commands",
+ "installed_commands.header": "Slash Commands",
"installed_commands.add": "Add Slash Command",
"installed_commands.empty": "No commands found",
"installed_commands.header": "Slash Commands",
@@ -1242,6 +1250,8 @@
"integrations.command.description": "Slash commands send events to external integrations",
"integrations.command.title": "Slash Command",
"integrations.header": "Integrations",
+ "integrations.done": "Done",
+ "integrations.add": "Add",
"integrations.incomingWebhook.description": "Incoming webhooks allow external integrations to send messages",
"integrations.incomingWebhook.title": "Incoming Webhook",
"integrations.oauthApps.description": "OAuth 2.0 allows external applications to make authorized requests to the Mattermost API.",
diff --git a/webapp/routes/route_integrations.jsx b/webapp/routes/route_integrations.jsx
index a9d86a5e2..afaf284e9 100644
--- a/webapp/routes/route_integrations.jsx
+++ b/webapp/routes/route_integrations.jsx
@@ -77,6 +77,12 @@ export default {
}
}
]
+ },
+ {
+ path: 'confirm',
+ getComponents: (location, callback) => {
+ System.import('components/integrations/components/confirm_integration.jsx').then(RouteUtils.importComponentSuccess(callback));
+ }
}
]
};
diff --git a/webapp/utils/async_client.jsx b/webapp/utils/async_client.jsx
index 185fa5b4e..674741b82 100644
--- a/webapp/utils/async_client.jsx
+++ b/webapp/utils/async_client.jsx
@@ -1257,7 +1257,7 @@ export function addIncomingHook(hook, success, error) {
});
if (success) {
- success();
+ success(data);
}
},
(err) => {
@@ -1280,7 +1280,7 @@ export function addOutgoingHook(hook, success, error) {
});
if (success) {
- success();
+ success(data);
}
},
(err) => {
@@ -1374,7 +1374,7 @@ export function addCommand(command, success, error) {
});
if (success) {
- success();
+ success(data);
}
},
(err) => {
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 24d1d6b19..05068f4ea 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -759,6 +759,12 @@ export const Constants = {
NotificationPrefs: {
MENTION: 'mention'
},
+ Integrations: {
+ COMMAND: 'commands',
+ INCOMING_WEBHOOK: 'incoming_webhooks',
+ OUTGOING_WEBHOOK: 'outgoing_webhooks',
+ OAUTH_APP: 'oauth2-apps'
+ },
FeatureTogglePrefix: 'feature_enabled_',
PRE_RELEASE_FEATURES: {
MARKDOWN_PREVIEW: {